Unityのボタンイベントをコードで記述する

Unityのボタンイベントは一般的にはインスペクターから登録しますが、今回はこれをコードだけで実現する方法を考えてみます
合わせて、Prefabで生成されたオブジェクトが生成されるタイミングでイベントに登録する方法も確認しましょう

実行結果

スペースキーを押すとCubeが作られます
攻撃ボタンをクリックするとイベントハンドラが実行されます

次のシーン構成からサンプルを作成して、どのような方法で実行されていくのかを確認しましょう
必要な時に自作でも活用(流用)できるかも考えましょう

シーン構成

ButtonEventSample_Codeでプロジェクトを作成しましょう

UIボタンを追加します

インスペクターではボタンイベントは次の場所で登録しますが、今回はこれを使わない方法を見ていきます

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

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

コード

CreateGameObjectスクリプト

prefabからオブジェクトを生成します
生成される場所が、押す度に変化させている仕組みを考えてみましょう

using UnityEngine;

public class CreateGameObject : MonoBehaviour
{
    [SerializeField]
    GameObject enemyObj;

    float count;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Vector3 createPos = new Vector3(
                transform.position.x + count++,
                transform.position.y,
                transform.position.z);

            Instantiate(enemyObj, createPos, Quaternion.identity);
        }
    }
}

AttackButtonClickスクリプト

Attackボタンがクリックされたときに実行されるイベントハンドラ(メソッド)を登録しています

using UnityEngine;
using UnityEngine.UI;

public class AttackButtonClick : MonoBehaviour
{
    public Button button;

    void Start()
    {
        button.onClick.AddListener(Attack);
    }

    private void Attack()
    {
        Debug.Log("攻撃した");
    }
}

ExtButtonClickスクリプト

prefabにアタッチします
オブジェクトが生成されたときに、イベントに自身のメソッドを登録します

using UnityEngine;
using UnityEngine.UI;

public class ExtButtonClick : MonoBehaviour
{
    void Start()
    {
        GameObject.Find("AttackButton")
                  .GetComponent<Button>().onClick
                  .AddListener(Attack2);
    }

    private void Attack2()
    {
        Debug.Log("攻撃された");
    }
}

まとめ

ボタンイベントをコードで実現する方法をみてきました
インスペクターへドラッグ&ドロップで登録する方法と同じことがコードでも可能でした

設計時点でシーンに存在するオブジェクトの場合、インスペクターから登録する方法をとってもOKです

コードに記述するメリットは

  • 同じスクリプト内にイベントの登録と実行コードが記述でき、アタッチするだけで良い
  • Prefabなどスタート時点ではシーンに存在しないオブジェクトでのイベント登録ができる

などが挙げられます

うまく使い分けて依存性の低いコーディングを目指しましょう

チャレンジ

いろいろな省略形を試してみましょう

オリジナル

using UnityEngine;
using UnityEngine.UI;

public class AttackButtonClick : MonoBehaviour
{
    public Button button;

    void Start()
    {
        button.onClick.AddListener(Attack);
    }

    private void Attack()
    {
        Debug.Log("攻撃した");
    }
}

メソッドに式本体を使用する

インテリセンスで簡単に移行できます
ラムダ記号(=>)を使って同じ実行コードとすることができます

using UnityEngine;
using UnityEngine.UI;

public class AttackButtonClick : MonoBehaviour
{
    public Button button;

    void Start()
    {
        button.onClick.AddListener(Attack);
    }

    private void Attack() => Debug.Log("攻撃した");
}

AddListenerの引数(Attack)に直接メソッドを代入してみる

引数の代入にラムダ式を使うというのは、このようなことです
メソッドそのまま入るイメージですね。大きいのはAttackというメソッド名が消えてしまっていることです
特に他からアクセスされることがなければ、これでいいですね

using UnityEngine;
using UnityEngine.UI;

public class AttackButtonClick : MonoBehaviour
{
    public Button button;

    void Start()
    {
        button.onClick.AddListener(() => Debug.Log("攻撃した"));
    }
}

おまけ(複数行の実行もできます)

using UnityEngine;
using UnityEngine.UI;

public class AttackButtonClick : MonoBehaviour
{
    public Button button;

    void Start()
    {
        button.onClick.AddListener(() =>
        {
            Debug.Log("攻撃した");
            Debug.Log("ーーーーー");
        }
        );
    }
}

AttackButtonClickスクリプトが無効の場合どうなるか考えてみましょう

削除しなくてもチェックボックルを外すだけてOKです

AttackButtonClickスクリプトの代わりにExtButtonClickスクリプトをアタッチしたらどうなるか考えてみましょう

C#,Unity,イベント

Posted by hidepon