Unity×C#でわかる!デリゲート : ゲーム開発で活きるイベント制御の基本
Unity×C#でわかる!デリゲート : ゲーム開発で活きるイベント制御の基本
高校生にもわかるプログラミング学習シリーズへようこそ!
「デリゲート」 って言葉、UnityやC#の学習を始めたばかりだとかなり見慣れないですよね。実はこれ、「関数を代わりに呼び出してくれる仕組み」 のことで、ゲーム開発でもとても役立ちます。今回の記事では、デリゲートの基礎を「そもそも何のために使うの?」というところから、Unityでの具体例まで解説していきます。
この記事のゴール: デリゲートの基本的な動作とメリットを理解し、Unity×C#でのプログラムに活かせるようになること。
1. デリゲートとは何か?「関数を差し込む仕組み」
「デリゲート」は、C#でとても重要な機能です。まずはざっくりとしたイメージからつかんでみましょう。
1-1. 関数を“差し込む”ってどういうこと?
デリゲートは簡単に言うと「関数を差し替えできる仕組み」です。もう少し砕けた表現をすると、「誰かの代わりに関数を呼び出してくれる仲介人」です。
- 例えるならリモコン
リモコンのボタンを押すとテレビの電源がついたり、エアコンの温度が変わったりしますよね。リモコン(=デリゲート)が家電操作(=関数)を代わりに実行してくれる感じです。 - どの家電を操作するのかはボタンに設定された動作次第。デリゲートの場合は、どの関数を実行するかをプログラム側で自由に設定できます。
1-2. 日常のたとえ話:部活の連絡係
高校生であれば、部活内での情報伝達を想像するとわかりやすいかもしれません。
- サッカー部の「キャプテン」が部員に連絡事項を伝える → 連絡デリゲート
- 吹奏楽部の「副部長」が部員に演奏予定を知らせる → 連絡デリゲート
それぞれ「キャプテン」と「副部長」は役割は違いますが、どちらも**連絡(=何かをする関数)**を部員に伝えるデリゲートのようなもの。呼び出す先が部員か顧問かで違いはありますが、同じフローで「連絡(関数)を実行」できます。
2. C#でのデリゲートの書き方
実際にC#コードでデリゲートを定義する流れを見てみましょう。
2-1. デリゲートを定義する
using System;
public class DelegateExample
{
// 1. デリゲートの宣言(int型を受け取って、戻り値がない関数を想定)
public delegate void ProcessDelegate(int value);
public static void Main()
{
// 2. 関数をデリゲートに割り当てる
ProcessDelegate process = PrintValue;
// 3. デリゲートを通して関数を呼び出す
process(100);
}
// 割り当てる先の関数
public static void PrintValue(int val)
{
Console.WriteLine("Value: " + val);
}
}
コード解説
-
delegate void ProcessDelegate(int value);
-
void
は関数の戻り値(なし)、int value
は関数の引数を表しています。 - 「intを受け取って何かをする」関数を差し替え可能にしたいときに使えるイメージです。
-
-
ProcessDelegate process = PrintValue;
-
PrintValue
という関数をprocess
という変数(デリゲート)に代入しています。
-
-
process(100);
-
PrintValue(100)
と同じ意味になります。デリゲートが呼び出し窓口になってくれるわけです。
-
2-2. どんなメリットがある?
-
呼び出す関数を簡単に差し替えられる
たとえばprocess = PrintValue;
の代わりに別の関数を割り当てれば、呼び出す内容をサッと変更可能。 -
プログラムの可読性と柔軟性が上がる
「何をするか」を別々に管理できるため、大きなシステムでもコードが整理されやすいです。
3. Unityでの活用イメージ:ボタン入力やイベント管理
3-1. GUIボタンが押されたら何をする?
Unityでよくあるシーンとして、「UIのボタンを押したらキャラクターがジャンプする」という処理があります。これをデリゲートを使って柔軟に実装できると便利です。
using UnityEngine;
using UnityEngine.UI;
public class ButtonHandler : MonoBehaviour
{
// デリゲート型
public delegate void ButtonAction();
// ボタンが押されたら実行するアクションを外部から設定できるようにする
public ButtonAction OnButtonPressed;
[SerializeField] private Button myButton;
void Start()
{
// ボタンが押されたらデリゲートを呼び出すよう設定
myButton.onClick.AddListener(() => {
if(OnButtonPressed != null)
{
OnButtonPressed();
}
});
}
}
コードのポイント
-
ButtonAction
は戻り値も引数もないデリゲート。 -
OnButtonPressed
は「ボタンが押されたときに呼び出したい関数」を差し替えられるように用意した変数です。 -
myButton.onClick.AddListener(...)
の中でOnButtonPressed()
を呼んでいるので、ボタンを押すたびに どんな関数でも 実行できます。
3-2. 実際にボタンでジャンプさせるスクリプト
using UnityEngine;
public class PlayerJump : MonoBehaviour
{
void Start()
{
// ButtonHandlerコンポーネントを取得
ButtonHandler handler = FindObjectOfType<ButtonHandler>();
// 「OnButtonPressed」デリゲートに、このスクリプト内のJump関数を登録
if(handler != null)
{
handler.OnButtonPressed = Jump;
}
}
public void Jump()
{
// 実際のジャンプ処理は省略。ここではログを表示
Debug.Log("Player Jump!");
}
}
-
handler.OnButtonPressed = Jump;
で、ボタンが押されたときに実行する処理を登録しているのがポイントです。 - ボタンを押したら
Jump()
が呼ばれ、「Player Jump!」と表示。 - 将来的に「ボタンでダッシュさせたい」と思えば、
handler.OnButtonPressed = Dash;
と書くだけでOK。
このように、「どの関数を呼ぶか」 を後から自由に差し替えるために、デリゲートが役立つのです。
4. なぜデリゲートを使うと便利なの?
ここまで具体例を見ましたが、実はデリゲートにはまだいくつかの魅力があります。
4-1. コードがシンプルになり、見通しが良くなる
-
デリゲートを使わない例
ボタンを押したらジャンプする場合、もしScript Aの中に「ボタン押されたら」というイベント処理を書き、Script Bの中で「ジャンプの中身」を書き・・・と、あちこちで処理を書きがちです。 -
デリゲートを使う例
「ボタンを押されたときは、こんな動作をしてね」という設定を1行で済ませられる。おかげでScript Aには「呼び出す部分」、Script Bには「実際の機能」という役割分担が生まれ、コードがすっきりします。
4-2. 設定が簡単で、デバッグもしやすい
デリゲートを使えば、呼び出す関数をまとめて一元管理できます。たとえば「このボタン押されたらジャンプと攻撃を同時にやらせたい!」と思ったら、以下のように複数のメソッドをまとめて登録することも可能です。
handler.OnButtonPressed = Jump;
handler.OnButtonPressed += Attack;
handler.OnButtonPressed += Dash;
-
OnButtonPressed
に関数を足していく書き方です。 - ボタンを押すと
Jump()
,Attack()
,Dash()
が順番に実行されます。
もし「ジャンプだけ実行しなくていいや」と思ったら handler.OnButtonPressed -= Jump;
で外せます。こうやって追加/削除を容易に管理できるのもデリゲートの利点です。
5. 高校生にも伝えたい!デリゲートを覚えるメリット
5-1. 学校の委員会活動を思い出してみよう
学校生活でも「委員会活動」がありますよね。行事委員が文化祭準備、風紀委員が服装チェック、体育委員が運動会準備など、それぞれやることは違うけど、呼び出されるタイミングは共通(先生からのお願いがあったときなど)。
デリゲートを使えば、同じ「呼び出し口」に対して、どの“委員”が動くかを動的に設定できるイメージ。先生は「行事係、出番だよ」「風紀係、出番だよ」と声をかけるだけで、具体的に何をするかは委員の仕事になっています。
5-2. プログラミングの柔軟性がアップ
学んでいくと、ゲームやアプリには様々なアクション(関数)が増えます。そのとき、プログラムのあちこちで「このタイミングでこれを呼びたい」という要望が出てきます。デリゲートを使うと、**「どこか1カ所に呼び出し口を用意」→「あとから好きなアクションを登録・解除」**という流れが確立できるため、複雑なシステムでもまとめやすくなります。
6. 一歩進んだ使い方:イベントとラムダ式
C#には、デリゲートをもっと便利に使う手段があります。ここではサクッと概要だけ。
6-1. イベント(event)
デリゲートに「複数の関数を登録・実行する」用途に特化した仕組みがイベントです。
public class Player
{
// イベントの宣言
public event Action OnDead;
public void Update()
{
// HPが0になったとき
if (hp <= 0)
{
// イベントを呼び出す
OnDead?.Invoke();
}
}
}
-
OnDead
にいろんな関数を登録しておけば、プレイヤーが死んだ時にまとめて呼び出しが可能。 - デリゲートと同じように追加・削除もできるので、より直感的です。
6-2. ラムダ式
さらに、「ちょっとした関数」をわざわざ命名せず、その場で記述する方法がラムダ式です。
handler.OnButtonPressed += () => {
Debug.Log("An anonymous function is called!");
};
-
() => { ... }
の部分がラムダ式。 - これにより、一度きりの簡単な動作なら「Jump関数を作るまでもない」ときに、コードをスッキリ書けます。
7. まとめ:デリゲートでプログラムを整理しよう
-
デリゲートの役割
- 関数を差し替えられる仕組み。呼び出す処理を自由に変えられる。
-
Unityでの応用
- ボタンが押された時や特定のイベントが発生した時に柔軟に関数を差し替える。
-
メリット
- コードがスッキリ&管理しやすい。
- 関数をあとから追加・削除できる。
高校生の皆さんにとっては、まだ耳慣れないキーワードかもしれませんが、デリゲートを覚えるだけでC#とUnityの理解が飛躍的に深まります。プログラムの規模が大きくなるほど、デリゲートが役に立つ場面は増えるはずです。ぜひコードを書きながら体験してみてください!
この記事を読んで「もっと実践したい!」と感じたあなたへ
Unity開発を効率よく進めるためには、実践的スキルと仲間の交流が大切。
おすすめステップは下記3つ:
1. 有料教材「どこでもUnity教室」でゲーム制作を短期マスター
- 5日でシンプルFPS完成: 初心者でも要点を網羅
- 最新InputSystem, FPS実装まで: つまずきやすいポイント先回り解説
- 購入特典: Discord招待+サンプルプロジェクト
2. 無料コミュニティで疑問即解消&モチベUP
- 初心者~中級OK: 学習ペースに合わせた質問・情報共有
- 質問サポートが充実: 講師や仲間に即相談
- 切磋琢磨できるから挫折しにくい
3. ゲーム開発所RYURYUがトータルサポート
- コナラ総販売200件超: 多様なUnity案件対応
- VR/AR/AI含む先端技術にも精通
- ゲームクリエイター甲子園/TGS出展実績多数
デリゲートのしくみを理解しておくと、Unityでのコード構造が一気に綺麗になります。ぜひ次のステップで学習を進めて、さらにクリエイティブなゲーム作りに挑戦してみてください!
Discussion