動的にボタンにデータを持った機能を加える


※)15.06.06 一番下に追記あり

動的にボタンを作成したときに、それぞれのボタンに対して情報を分けた処理をさせたい。
ラムダ式でパラメータ渡そうと思ったけどうまく行かない。

using UnityEngine;
using UnityEngine.UI;
using System;

public class Test : MonoBehaviour {
	// ボタンのプレハブ
	public GameObject buttonPrefab;

	// Start.
	void Start () {
		for (int i = 0; i < 10; ++i) {
			GameObject buttonGO = (GameObject)Instantiate(this.buttonPrefab);
			buttonGO.transform.SetParent(this.transform, false);

			Button button = buttonGO.GetComponent<Button>();
			button.onClick.AddListener(() => {
				this.DoSomething(i);
			});
		}			
	}

	// なにか処理する
	void DoSomething(int num) {
		print(num);
	}
}

どうもローカル変数を参照しているみたい。
なので、メソッドを分けて引数で数字を渡すとうまくいった。

using UnityEngine;
using UnityEngine.UI;
using System;

public class Test : MonoBehaviour {
	// ボタンのプレハブ
	public GameObject buttonPrefab;

	// Start.
	void Start () {
		for (int i = 0; i < 10; ++i) {
			GameObject buttonGO = (GameObject)Instantiate(this.buttonPrefab);
			buttonGO.transform.SetParent(this.transform, false);

			Button button = buttonGO.GetComponent<Button>();
			this.AddButtonEvent(button, i);
		}			
	}

	// ボタンに機能を付与する
	void AddButtonEvent(Button button, int num) {
		button.onClick.AddListener(() => {
			this.DoSomething(num);
		});
	}

	// なにか処理する
	void DoSomething(int num) {
		print(num);
	}
}

余計なメソッドを作らずに、Actionを作って実行するなら

using UnityEngine;
using UnityEngine.UI;
using System;

public class Test : MonoBehaviour {
	// ボタンのプレハブ
	public GameObject buttonPrefab;

	// Start.
	void Start () {
		// ボタンに機能を付与する
		Action<Button, int> addButtonEvent = (Button button, int num) => {
			button.onClick.AddListener(() => {
				this.DoSomething(num);
			});
		};

		for (int i = 0; i < 10; ++i) {
			GameObject buttonGO = (GameObject)Instantiate(this.buttonPrefab);
			buttonGO.transform.SetParent(this.transform, false);

			Button button = buttonGO.GetComponent<Button>();
			addButtonEvent(button, i);
		}			
	}

	// なにか処理する
	void DoSomething(int num) {
		print(num);
	}
}

これでいいのかな?
もっといいやり方があるような気がするけど…

追記 15.06.06
ローカル変数を新たに作って、そちらへ代入する方法でもできた。。
以前試したらうまくいかなかったんだけどなぁ。。。

using UnityEngine;
using UnityEngine.UI;
using System;

public class Test : MonoBehaviour {
	// ボタンのプレハブ
	public GameObject buttonPrefab;

	// Start.
	void Start () {
		for (int i = 0; i < 10; ++i) {
			GameObject buttonGO = (GameObject)Instantiate(this.buttonPrefab);
			buttonGO.transform.SetParent(this.transform, false);

			Button button = buttonGO.GetComponent<Button>();

			// ここで新たな変数へ代入する
			int j = i;

			button.onClick.AddListener(() => {
				print(j);
			});
		}           
	}
}

“動的にボタンにデータを持った機能を加える” への1件のフィードバック

  1. ももせ より:

    ローカル変数を参照してしまう問題で困っていました。

コメントを残す