Unityで使えるイベント

2020年9月9日

Unityで使えるイベントは、UnityイベントとC#のイベントの2つがあります。
Unityイベントでよく使われるのは、Buttonイベントでインスペクター から登録が可能です。
ここでは、ボタン以外でイベントを扱いたい場合について説明します。

Unityイベントチュートリアル

チュートリアルを通して、検証してみましょう

新しくUnityEventTestプロジェクトを作成します。

3Dでプロジェクトを作成します。

シーンをUnityEventSceneとして、保存します。

あとで、C#イベントも作成するため、シーンを分けます。

Cubeオブジェクトを作成します。

名前をPlayerにします。

PlayerController_UnityEventスクリプトを作成します。

このコードは、スペースキーを押下されたらメソッドを呼び出すものですが、どのメソッドが呼び出されるのかを記述していません。また、どこから呼び出されたのかもわかりません。スペースキーを押下すると何かのメソッドが呼び出されることがこのコードの目的になります。
このようなコードは、結びつきが弱い(依存性が低い)コードと言います。

コード

using UnityEngine;
using UnityEngine.Events;

public class PlayerController_UnityEvent : MonoBehaviour
{
    public UnityEvent OnCubeAction;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            OnCubeAction?.Invoke();
        }
    }
}

コードの説明

イベントが発生した時に呼び出されるコードを代入するメンバーを宣言します。
OnCubeActionには、あとでメソッドを代入します。メソッドを代入できる変数をデリゲートと呼びます
(戻り値なし、引数なし)

public UnityEvent OnCubeAction;

?は、「もしnullでなければ」を略するもので、if(OnCubeAction != null)と同じです。
Invoke()で、メソッド(OnCubeAction)を呼び出します。
スペースキーを押下すると実行されます。

OnCubeAction?.Invoke();

CubeAction_UnityEventスクリプトを作成します。

コード

using UnityEngine;

public class CubeAction_UnityEvent : MonoBehaviour
{
    public void ColorChange()
    {
        GetComponent<Renderer>().material.color = Color.green;
    }

    public void Rotate()
    {
        transform.Rotate(Vector3.forward * 10);
    }
}

コードの説明

Cubeのカラーを緑にします

GetComponent<Renderer>().material.color = Color.green;

z軸を中心に10°回転します

transform.Rotate(Vector3.forward * 10);

Playerゲームオブジェクトに2つのスクリプトをアタッチします。

スクリプトをアタッチすると、インスペクター にコンポーネントの1つとして登録されます。
コンポーネントは、他にTransform,MeshRenderer,BoxColliderなどがあります。

イベントを登録する

インスペクター のPlayerController_UnityEventのOnCubeAction()に2つのメソッドを登録します
Unityイベント型のOnCubeActionメンバーには、複数のメソッドを登録することができます

実行してみましょう

スペースキーを押下すると、Cubeが緑になって、10°回転するか確認しましょう

Tips

インスペクターから登録しない方法
CubeAction_UnityEventスクリプトに次のコードを追記します。

private void Start()
{
    var action = GetComponent<PlayerController_UnityEvent>().OnCubeAction;

    action.AddListener(ColorChange);
    action.AddListener(Rotate);
}

インスペクターのマイナスボタンで登録したイベントを削除して確認しましょう

応用

イベントを宣言しているスクリプトとイベントと登録するスクリプトが別のオブジェクトにアタッチされている場合

objAにアタッチされているスクリプト

using UnityEngine;
using UnityEngine.Events;

public class EventSample : MonoBehaviour
{
    public UnityEvent actionEvent;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            actionEvent.Invoke();
        }
    }
}

objBにアタッチされているスクリプト(インスペクターで登録しない場合)

インスペクターのEventSampleにobjAをアウトレット接続しておきます

using UnityEngine;

public class Act : MonoBehaviour
{
    [SerializeField]
    EventSample eventSample;

    private void Start()
    {
        eventSample.actionEvent.AddListener(AttackHandler);
        eventSample.actionEvent.AddListener(DiffencdHandler);
    }
    public void AttackHandler()
    {
        Debug.Log("Show");
    }

    public void DiffencdHandler()
    {
        Debug.Log("Diffance");
    }
}

objBにアタッチされているスクリプト(インスペクターで登録する場合)

objAのEventSampleコンポーネント(objAを選択して、インスペクターを確認)のイベントActionEvent欄に次の2つを登録します

using UnityEngine;

public class Act : MonoBehaviour
{
    public void AttackHandler()
    {
        Debug.Log("Show");
    }

    public void DiffencdHandler()
    {
        Debug.Log("Diffance");
    }
}

C#イベントチュートリアル

C#で定義されているEventHandlerを使って、イベントを作成します。

シーンをDotNetEventとして、保存します。

プロジェクトビューで、新しくシーンを作成します。名前は、DotNetEventとします。

Cubeオブジェクトを作成します。

名前をPlayerにします。

PlayerController_DotNetEventスクリプトを作成します。

コード

using System;
using UnityEngine;

public class PlayerController_DotNetEvent : MonoBehaviour
{
    public event EventHandler OnCubeAction;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            OnCubeAction?.Invoke(this, EventArgs.Empty);
        }
    }
}

コードの説明

OnCubeActionには、あとでメソッドを代入します。
(戻り値なし、引数 object sender, EventArgs e)イベントを発生させたインスタンスとその情報

public event EventHandler OnCubeAction;

?は、「もしnullでなければ」を略するもので、if(OnCubeAction != null)と同じです。
Invoke()で、メソッド(OnCubeAction)を呼び出します。
イベントを発生させたインスタンスは、このインスタンス自身とし、情報は特に提供しないため、Emptyとします。

OnCubeAction?.Invoke(this, EventArgs.Empty);

CubeAction_DotNetEventスクリプトを作成します。

コード

using System;
using UnityEngine;

public class CubeAction_DotNetEvent : MonoBehaviour
{
    private void Start()
    {
        PlayerController_DotNetEvent action = GetComponent<PlayerController_DotNetEvent>();

        action.OnCubeAction += ColorChange;
        action.OnCubeAction += Rotate;
    }

    public void ColorChange(object sender, EventArgs e)
    {
        GetComponent<Renderer>().material.color = Color.green;
    }

    public void Rotate(object sender, EventArgs e)
    {
        transform.Rotate(Vector3.forward * 10);
    }
}

コードの説明

PlayerController_DotNetEventコンポーネントを取得します。この名称は、クラス名(スクリプト名)と同じです。

PlayerController_DotNetEvent action = GetComponent<PlayerController_DotNetEvent>();
ポイント

インテリセンス(暗黙的な型の使用)で、型宣言をvarにすることで短く見やすくすることができます。

イベントを登録する

イベントが発生したら呼び出されるメソッドを登録します
PlayerController_DotNetEventクラスのOnCubeActionメンバーに呼び出したいメソッドを代入します。
+=で追加代入するイメージです。event では、=(イコール)での代入は許されていません。
-=でこのグループから外すことができます。

action.OnCubeAction += ColorChange;
action.OnCubeAction += Rotate;

Playerゲームオブジェクトに2つのスクリプトをアタッチします。

スクリプトをアタッチすると、インスペクター にコンポーネントの1つとして登録されます。
コンポーネントは、他にTransform,MeshRenderer,BoxColliderなどがあります。

実行してみましょう

スペースキーを押下すると、Cubeが緑になって、10°回転するか確認しましょう

おすすめ動画

ドキュメント

2020年9月9日Unity

Posted by hidepon