はじめに
Unity C# の delegate は、関数やメソッドへの参照を格納することができる型で、イベントやコールバックの実装に便利な機能です。C# ではデリゲートを使うと、特定の条件下で実行する関数を動的に選択したり、複数の関数をまとめて呼び出したりできます。これは、コールバック処理やイベント処理によく用いられます。
デリゲートとは?
public delegate void MyDelegateType(); // 引数なし、戻り値なしのデリゲート型を宣言
public class MyClass
{
public MyDelegateType myDelegate; // デリゲート型の変数を宣言
public void MyMethod()
{
if (myDelegate != null)
myDelegate(); // デリゲートに代入されたメソッドを呼び出す
}
}
なるほどわからん。
デリゲートの使用例
using UnityEngine;
public class DelegateExample : MonoBehaviour
{
// 戻り値なし、引数なしのデリゲート型を定義
public delegate void SimpleDelegate();
// デリゲート変数の宣言
public SimpleDelegate myDelegate;
void Start()
{
// デリゲート変数にメソッドを代入
myDelegate = MyFunction;
// デリゲートを実行
myDelegate?.Invoke(); // 安全に呼び出すために null チェックも含める
}
void MyFunction()
{
Debug.Log("MyFunction is called!");
}
}
要は変数に関数入れて実行できるってこと。
この例では、SimpleDelegate というデリゲート型を宣言し、それを通して MyFunction を呼び出しています。
デリゲートを使う理由
- コールバック処理: 処理が完了した後に別の処理を実行したい場合に便利です。
- イベント処理: Unityの UnityEvent や Action 型もデリゲートの一種で、イベントを設定したり、複数の関数をまとめて実行するのに役立ちます。
- 動的な関数呼び出し: 実行時にメソッドを動的に変更したり、組み合わせたりすることができます。
イベントの実装にも使われる
Unity では delegate と event を組み合わせてイベント処理を行うことも一般的です。たとえば、プレイヤーの体力が尽きたときなどに特定のメソッドを呼び出す場合、デリゲートを使って柔軟にイベントを設定することができます。
Action と Func の簡単な使い方
C# の Action と Func もデリゲートの一種で、簡単に使える汎用デリゲートです。Action は戻り値がないメソッド、Func は戻り値があるメソッドに適しています。
// Action の例(引数なし、戻り値なし)
Action action = () => Debug.Log("Action called");
action.Invoke();
// Func の例(引数なし、戻り値あり)
Func<int> func = () => 42;
int result = func.Invoke();
Debug.Log(result);
なるほどわからん。
結果
- デリゲートはメソッドの参照 を格納する型で、柔軟なメソッド呼び出しができる。
- イベントやコールバック を作成するのに便利で、条件に応じた処理を設定できる。
- Unity のスクリプトでも 柔軟な動的処理 やイベントシステムの実装に活用される。
デザインパターンと利便性についてなどあるが、なるほどわからん。
FSM作るよ
using UnityEngine;
public class SimpleFSM : MonoBehaviour
{
// 各状態の処理を表すデリゲート定義
public delegate void State();
// 現在の状態を保持するデリゲート変数
private State currentState;
void Start()
{
// 初期状態を設定
TransitionTo(IdleState);
}
void Update()
{
// 現在の状態を実行
currentState?.Invoke();
}
// 状態遷移を行うメソッド
void TransitionTo(State newState)
{
currentState = newState;
}
// 各状態の処理
void IdleState()
{
Debug.Log("Idle");
if (Input.GetKeyDown(KeyCode.Space))
{
// ジャンプ状態に遷移
TransitionTo(JumpState);
}
}
void JumpState()
{
Debug.Log("Jumping");
if (Input.GetKeyDown(KeyCode.LeftShift))
{
// 走る状態に遷移
TransitionTo(RunState);
}
}
void RunState()
{
Debug.Log("Running");
if (Input.GetKeyDown(KeyCode.S))
{
// アイドル状態に遷移
TransitionTo(IdleState);
}
}
}
実装の詳細
- 状態デリゲート State:
- State は、各状態のメソッドシグネチャとして void 戻り値、引数なしのデリゲートです。
- IdleState, JumpState, RunState は、この State デリゲートと一致するシグネチャを持つメソッドとして定義されています。
- currentState デリゲート変数:
- 現在の状態を表し、TransitionTo メソッドで更新されます。
- Update メソッドで毎フレーム currentState?.Invoke() により現在の状態メソッドを呼び出します。
- 状態遷移メソッド TransitionTo:
- 引数で渡された State デリゲートを currentState に代入し、状態遷移を行います。
- 各状態メソッド:
- IdleState, JumpState, RunState の各メソッドがそれぞれの状態における処理を実行し、特定のキー入力に基づいて次の状態へと遷移します。
拡張方法
この構造は拡張しやすく、以下のように使うことができます:
- 新しい状態の追加:
- 例えば「しゃがみ状態」を追加する場合、新しいメソッド CrouchState を定義し、必要な条件で TransitionTo(CrouchState); とするだけで対応できます。
- 汎用的なパラメータの管理:
- 状態が特定の情報(たとえば体力やスタミナ)を参照する必要がある場合、クラスのフィールドにパラメータを追加して、各状態メソッドで利用できます。
まとめ
- シンプルで柔軟: 状態の追加・削除が容易で、動作もわかりやすい。
- パフォーマンスに優れる: デリゲートを用いてメソッド参照を保持するため、処理のオーバーヘッドが少ない。
- Unity のフレームごとに変化する状態に最適: Update で呼び出すことで、フレームごとの状態確認と切り替えが自然に行えます。
デリゲートを使った FSM は、簡潔でわかりやすく、Unity のスクリプト内で動作を効率的に管理できます。
おわりに
今作ってるゲームの、タイマー終わったらキューに実行スタックしていくのに使えそう。

