Unity コールバックの受け取り方あれこれ

Unityゲーム開発に使えるコールバックの備忘録

# System.Action
**System.Action** と **System.Func** を使えば、デリゲートの形式を宣言する必要がないので楽。

### 使用例
DoTweenと組み合わせて、フェードアウト・インしつつ何かを実行するメソッドを作ってみた。
引数でColorを渡してやるようにすれば、ブラックアウト、ホワイトアウト好きなものにカスタマイズもできる。

```FadeController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using DG.Tweening;

namespace Sample
{
    public class FadeController : MonoBehaviour
    {
       [SerializeField] CanvasGroup fadeCanvas;
       [SerializeField] Image image;
        System.Action action;

        public void FadeAction(System.Action action)
        {
            image.color = Color.black;

            var sequence = DOTween.Sequence();
            sequence.Append(fadeCanvas.DOFade(1.0f, 2.0f))
                    .AppendCallback(() =>
                    {
                        action();  //画面が真っ暗になったら、引数のactionメソッドを実行
                    })
                    .Append(fadeCanvas.DOFade(0.0f, 2.0f))
                    .OnComplete(() => SetActive(false));
        }
    }
}
```

# System.Func

返り値がある場合には **System.Func** を使用します。
値を渡して、それが ~~ ならば、最後の引数を返す　　...といった処理が書ける。

### 使用例

```Sample.cs
using System;

public class Sample 
{

    public void Calculate()
    {
        Func<bool,bool,string> callBack = (valueA,valueB) =>
         {
            if (valueA && valueB)
             {
                 return "TRUE!";
             }
             return "FALSE!";
         };
    }
}
```
# UnityEvent
>シーンに保存することができる引数を持たない永続的なコールバック。

...スクリプリファレンス分からない。

[UnityEvent](https://docs.unity3d.com/ja/2017.4/ScriptReference/Events.UnityEvent.html)とSystem.Actionの違いについては下記で紹介されていた。
[【Unity】UnityEventの用法と用量](https://www.urablog.xyz/entry/2016/09/11/080000)

**特徴**
- 機能としての違いはない
- Unityのインスペクター上に表示されるため、直感的
- 複数のイベントを簡単に登録できる。
- Invoke()を使うと登録したメソッドが一斉に実行される。


```UnityEventSample.cs
using UnityEngine;
using UnityEngine.Events;
using System.Collections;

public class UnityEventSample: MonoBehaviour
{
    [SerializeField]UnityEvent m_MyEvent;

    void Start()
    {
        if (m_MyEvent == null)
            m_MyEvent = new UnityEvent();

        m_MyEvent.AddListener(Ping); //Ping()メソッドを登録
    }

    void Update()
    {
        if (Input.anyKeyDown &amp;&amp; m_MyEvent != null)
        {
            m_MyEvent.Invoke(); //イベントの実行
        }
    }

    void Ping()
    {
        Debug.Log("Ping");
    }
}
```
UnityのUGUIボタンにあるような奴がインスペクター上に現れる。
![スクリーンショット 2019-02-07 17.51.33（2）.png](https://qiita-image-store.s3.amazonaws.com/0/256717/8590521d-9fb7-ace8-0f44-26d974cf0420.png)

```ExampleClass.cs
using UnityEngine;
using UnityEngine.Events;

[System.Serializable]
public class MyIntEvent : UnityEvent<int> //引数の型を指定しておく
{
}

public class ExampleClass : MonoBehaviour
{
    public MyIntEvent m_MyEvent;

    void Start()
    {
        if (m_MyEvent == null)
            m_MyEvent = new MyIntEvent();

        m_MyEvent.AddListener(Ping);
    }

    void Update()
    {
        if (Input.anyKeyDown &amp;&amp; m_MyEvent != null)
        {
            m_MyEvent.Invoke(5);
        }
    }

    void Ping(int i) //登録するメソッドにint型引数を持たす
    {
        Debug.Log("Ping" + i);
    }
}
```
## UnityAction
[UnityAction](https://docs.unity3d.com/ja/current/ScriptReference/Events.UnityAction.html)というコールバック関数もある。

>UnityEvent で使用される引数なしのデリゲートです。


違いや使い分けについては、[UnityEventコールバック関数の設定方法について](http://unitygeek.hatenablog.com/entry/2017/11/16/104324)が参考になった。





# 参考
[UnityEvent でコールバックする](http://fantom1x.blog130.fc2.com/blog-entry-252.html)
[C# 備忘録 コールバックについて](https://qiita.com/r-ngtm/items/6e5e5fbe6a58df3b1bc8)
[UnityEventコールバック関数の設定方法について](http://unitygeek.hatenablog.com/entry/2017/11/16/104324)