【Unity・C#】ActionとFuncについてまとめる
私事ですが、Action・Funcを使用する頻度が増えてきました。
しっかりと認識したことがなかったためメモを残しておきます。
対応表
すべて using System; を使用します。
型構文 | 説明 |
---|---|
Action | 戻り値なし・引数なし |
Action<T, ..., > | 戻り値なし・引数あり |
Func<TResult> | 戻り値あり・引数なし |
Func<T, ..., TResult> | 戻り値あり・引数あり |
基本的な使い方
ActionやFuncは「関数を参照するための型」です。
まずは一例を載せておきます。
using System; using UnityEngine; public class SampleComponent: MonoBehaviour { //----------------------------------------------------------------------- // メンバ変数 //----------------------------------------------------------------------- // 1: Action型の変数を定義 private Action m_Action; //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 初期化処理 private void Start() { // 2: m_ActionにShowLog()関数の参照を渡す m_Action += ShowLog; } // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 3: m_Action.Invoke()で参照させた関数が呼ばれる // →ShowLog()が呼ばれる m_Action.Invoke(); } } // 破壊時 private void OnDestroy() { // 4:使い終わったら参照を消す m_Action-= ShowLog; } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // ログ表示 private void ShowLog() { Debug.Log("Hello World!"); } }
メンバ変数に対して+=【関数】で登録します。
任意のタイミングでInvoke()を呼んで関数を実行できます。
使わなくなったら-=【関数】で解除おきましょう。
気づいた方もいるかもしれませんが、
+=や-=などを使って、関数の登録/解除を視覚的に分かりやすくしてくれています。
普段の計算式のように扱えるのはevent君のおかげですね。
ありがたや…。ありがたや…。
learn.microsoft.com
また、「関数を参照するための型」なので引数にもできたりします。
using System; using UnityEngine; // サンプルコンポーネント public class SampleComponent: MonoBehaviour { //----------------------------------------------------------------------- // メンバ変数 //----------------------------------------------------------------------- private ExecuteInsteadComponent m_ExeComp = null; //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 初期化処理 private void Start() { // 1: 実行を行うコンポーネント m_ExeComp = GetComponent<ExecuteInsteadComponent >(); } // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 2: 引数に自身の関数を渡す m_ExeComp .InsteadFunction(ShowLog); } } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // ログ表示 private void ShowLog() { Debug.Log("Hello World!"); } }
using System; using UnityEngine; // 代わりに関数を実行するコンポーネントクラス public class ExecuteInsteadComponent : MonoBehaviour { // 3: 関数実行 // →SampleComponentのShowLog()を処理 public void InsteadFunction(Action action) { action.Invoke(); } }
SampleComponentでは処理を行わず、
ExecuteInsteadComponent側で処理をさせるサンプルです。
private関数でも関係なく実行が可能です。
Action Delegate
Action・Action<T>は、「戻り値を持たない関数を参照するための型」です。
Action
戻り値なし・引数を持たない関数はこちら。
日本語訳だとAction代理人となっていますが、
デリゲートと覚えてしまった方がよいです。
learn.microsoft.com
using System; using UnityEngine; // Actionのサンプル public class SampleComponent : MonoBehaviour { //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 関数を渡して実行 ActionExecute(ShowLog); } } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // Action実行 // void Hoge() と同じ private void ActionExecute(Action action) { action.Invoke(); } // ログ表示 private void ShowLog() { Debug.Log("Hello World!"); } }
Action<T>
戻り値なし・引数を持つ関数はこちら。
Actionの後の<>の中に型を入れることで
引数付きの関数を入れられるようになります。
Invokeの()内に自分で記述した引数を入れる感じです。
learn.microsoft.com
using System; using UnityEngine; // Action<T>のサンプル public class SampleComponent : MonoBehaviour { //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 関数を渡して実行 ActionExecute(ShowLog); } } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // Action<T>実行 // void Hoge(int value1) と同じ private void ActionExecute(Action<int> action) { action.Invoke(0); } // ログ表示 private void ShowLog(int value1,int value2) { Debug.Log("Value1 : "+ value1); } }
引数の数について
ちなみに引数に持っていける数は最大で16個です。
(そんなにいる…?)
learn.microsoft.com
Func Delegate
Func<TResult>・Func<T,TResult>は、「戻り値を持つ関数を参照するための型」です。
Func<TResult>
戻り値あり・引数を持たない関数はこちら。
Action<T>とは違い、<>の中に入れた型がそのまま戻り値となります。
learn.microsoft.com
using System; using UnityEngine; // Func<TResult>のサンプル public class SampleComponent : MonoBehaviour { //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 関数を渡して実行 FuncExecute(GetFlg); } } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // Func実行 // bool Hoge() と同じ private void FuncExecute(Func<bool> func) { bool flg = func.Invoke(); if (flg) { Debug.Log("Hello World!"); } } // trueを返す関数 private bool GetFlg() { return true; } }
Func<T,TResult>
戻り値あり・引数を持つ関数はこちら。
こちらは引数の数にかかわらず、
一番最後に入れた型が戻り値となります。
learn.microsoft.com
using System; using UnityEngine; // Func<TResult,T>のサンプル public class SampleComponent : MonoBehaviour { //----------------------------------------------------------------------- // Unityメゾット //----------------------------------------------------------------------- // 更新処理 private void Update() { if (Input.GetMouseButtonDown(0)) { // 関数を渡して実行 FuncExecute(GetFlg); } } //----------------------------------------------------------------------- // 内部メゾット //----------------------------------------------------------------------- // Func実行 // bool Hoge(int value) と同じ private void FuncExecute(Func<int,bool> func) { bool flg = func.Invoke(1); if (flg) { Debug.Log("Hello World!"); } } // trueを返す関数 private bool GetFlg(int value) { bool ret = false; if (value >= 0) { ret = true; } return ret; } }
引数の数について
こちらもAction<T>と同じく、引数に持っていける数は最大で16個です。
どれだけ引数があろうと一番最後が戻り値となります。
learn.microsoft.com
参考にしたもの
・デリゲートとイベント | Microsoft Learn
・厳密に型指定されたデリゲート | Microsoft Learn
・標準的な .NET イベント パターン | Microsoft Learn
・Delegate クラス (System) | Microsoft Learn
・event - C# リファレンス | Microsoft Learn
・Action 代理人 (System) | Microsoft Learn
・https://learn.microsoft.com/ja-jp/dotnet/api/system.func-1?view=net-7.0