Toshusai blog

知識の保管庫

Unityでボタンに引数付きのイベントをスクリプトから設定する

Unityでボタンに引数付きのイベントをスクリプトから設定する

prefabとかでスクリプトからボタンを作るときに、ボタンごとに違うOnClick()イベントを渡したい。バージョンはUnity2017.2.0f2を使った。

ボタンにイベントをスクリプトから設定する

Start()下2行目
button.GetComponent<Button>().onClick.AddListener(Hello);
スクリプトから設定されたイベントはエディタ上のButtonコンポーネントに表示されないので注意。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour {

    public GameObject canvas;//エディタから指定
    public GameObject prefab;//エディタから指定

    void Start () {
        GameObject button = Instantiate(prefab, canvas.transform);
        button.GetComponent<Button>().onClick.AddListener(Hello);
    }

    void Hello(){
        Debug.Log ("Hello world!");
    }
}

ボタンに引数付きのイベントをスクリプトから設定する

引数付きのイベントを渡すにはラムダ式を使う必要がある。 しかし、注意すべきはラムダ式で使う変数を変更した場合、全てのラムダ式に反映されてしまう現象。 ラムダ式はその変数へのポインタをメモリに入れているのが原因らしい。 そこで一時変数を宣言してラムダ式に使う事で、ボタン毎に異なるイベントを設定することができる。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour {

    public GameObject canvas;//エディタから指定
    public GameObject prefab;//エディタから指定

    void Start () {
        for(int i = 0; i < 5; i++){
            GameObject button = Instantiate(prefab, canvas.transform);
            string tmp = i.ToString ();//一時変数
            button.GetComponent<Button>().onClick.AddListener(() => {Hello(tmp);});
        }
    }
    
    void Hello(string str){
        Debug.Log ("Hello " + str + "!");
    }
}

もし、次のように書いてしまったら、全てのボタンはHello 5!とコンソールに出力するイベントを持つ事になる。

button.GetComponent<Button>().onClick.AddListener(() => {Hello(i.ToString());});

参考