シーンからGameObjectを検索して自動アタッチ

Unityを使っているとよくやるのがクラスの変数にシーン上にあるGameObjectをアタッチするという行為
GameObjectの数が少なければ簡単なんだけれど
* 階層が深い
* デザイナーから納品されたもの

などといった場合にはどこに目的のものがあるのか探したり、間違えて選択してしまうとインスペクタが変わって即座にアタッチできなかったりと少し手間がかかってしまう。

その手間を多少減らすためにAttributeを追加してシーン上から検索して自動でアタッチしてくれるようにEditor用の拡張を追加

機能紹介

こんな風に参照の右にボタンを追加して押せばシーンから該当のオブジェクトを検索してアタッチしてくれる。

[SerializeField, UniUtil.Attribute.FindObjects("GameObject")]
private GameObject obj;

この機能を使う場合変数のAttributeを追加してやるだけ。
Attributeの引数に指定したオブジェクトが検索条件となる。

ただ、この方法で配列を行おうとするとすべて同じオブジェクトをアタッチしてしまってとても使えない。

なので配列のときに利用できる特殊な指定方法として

[SerializeField, UniUtil.Attribute.FindObjects("GameObject ({0})")]
private List<GameObject> bbb;

このように記述することが可能になっている。
FindObjectsAttributeは配列のときには指定した検索条件にstring.Format("条件", index);を実行するためオブジェクト名に連番をつけておけばインデックスを考慮したオブジェクトをアタッチしてくれる。

開発メモ

この機能は実際とても簡単なコードで実現している。
単にPropertyDrawerでGameObject.Findを実行するだけだ。

ただ配列の時だけ少し特殊なことをやってる。

Editor上でFindObject

PropertyDrawerの引数にあるSerializedPropertyは配列全体ではなく要素の1つ分になっている。
配列のプロパティパスを見ると【変数名】.Array.data[【インデックス】]となっている。 現在のプロパティの親のプロパティさえ取得できれば親なのか判別できるため

37行目以降でおこなっているように.でパスを切って3以上の個数になる場合は配列の可能性があるのでチェックを行う。
配列なのか判別できればdata[【index】]正規表現を利用してインデックスを取得してstring.Format("条件", index);で検索条件を利用するだけだ。
string.Formatを利用しているので
* 001のような形式
* プレフィックス
などある程度のパターンはどうにかなる。 今後はこの拡張をして少しずつ更新して便利にしていこうかな。