複数のButtonのOnClickイベントのパラメータに一括で`0, 1, 2,...`のように連番を設定する
Button
のonClickのイベントの引数に0から順番にいっぺんに数字を入れたいことってありますよね。
これを自動化するスクリプトを紹介します。続きからどうぞ。
Editorフォルダ以下の適当なスクリプトに入れてください。
(追記:RegisterIntPersistentListenerだと、OnClickに要素が何もないときにエラーになるので、その場合AddIntPersistentListenerにした)
/// <summary> /// ButtonのOnClickイベントに連番のパラメータを設定する /// </summary> /// <remarks> /// この機能ではパラメータを連番に設定するかわりに、(スクリプト上の困難さから妥協点として)メソッドがダミーに切り替わる仕様になっている /// なので、まずこの機能を使ってパラメータを設定してから、呼び出すメソッドを入れる必要がある /// </remarks> [MenuItem("Tools/Set Sequential Onclick Parameters")] static void SetSequentialOnclickParameters() { var selections = Selection.gameObjects.ToList(); // Selectionで取得されるオブジェクト群は順不同なのでヒエラルキー順にソートする // 1つしかない子オブジェクトをピックアップしてる場合は親のSiblingIndexを対象にする bool isParent = false; if (selections.All(x => x.transform.GetSiblingIndex() == 0)) { selections = selections.Select(x => x.transform.parent.gameObject).ToList(); isParent = true; } selections.Sort((a, b) => a.transform.GetSiblingIndex().CompareTo(b.transform.GetSiblingIndex())); // 元のButtonに対象を戻す if (isParent) { selections = selections.Select(x => x.GetComponentInChildren<Button>().gameObject).ToList(); } if (selections.Any(x => x.GetComponent<Button>() == null)) { Debug.LogError("選択したオブジェクトはすべてButtonコンポーネントがアタッチされている必要があります。"); return; } // 実行 for (int i = 0; i < selections.Count; i++) { if (selections[i].GetComponent<Button>().onClick.GetPersistentEventCount() > 0) { UnityEditor.Events.UnityEventTools.RegisterIntPersistentListener( selections[i].GetComponent<Button>().onClick, 0, selections[i].transform.SetSiblingIndex, i); } else { UnityEditor.Events.UnityEventTools.AddIntPersistentListener( selections[i].GetComponent<Button>().onClick, selections[i].transform.SetSiblingIndex, i); } } }
使い方は、
- パラメータを連番にしたいButtonオブジェクトをすべて選択
Tools/Set Sequential Onclick Parameters
を呼び出す(すると連番が設定される)- そのあとに、呼ぶメソッドの設定をする
となっています。
…実はここにいたるまでに紆余曲折があり、リフレクションを使って内部APIを呼び出したり、PersistentCall
やらMethodInfo
やら、およそ通常のUnity開発では使わないようなクラスまで使って奮闘したのですが、パラメーターだけ変更する、というようなストレートな解決策は見つからず、
数時間にわたる調査の末、苦肉の策として、SetSiblingIndex
を設定する仕組みにしています。
なのでメソッドを設定してからパラメータを変えるのではなく、このスクリプトでパラメータを設定してからメソッドを設定してください。パラメータは引き継がれます。 一応手間としては変わらないはず。
SetSiblingndex
にしたのは、GameObject
かTransform
、つまり全てのオブジェクトからアクセスできるメソッドの中で、引数がint
ひとつで戻り値がvoid
のものがこれだけだったためです。
う~んしかし苦しい。(OnClickに限らず)Editor上で設定したイベントのパラメータだけスクリプトから変更したいという需要は割と大きいと思うのですが、現状イベント丸ごとでしか扱えないようです。