親GameObjectから子要素を取得してforeachしたい
レイヤーを決めながら進めると、どうしても親子関係の設定方法によってはしっくり来るコードが書けないんですよね。
今回はタイトルの通り、親のGameObjectから子要素を取得し、子要素をGameObjectとしてforeachをぶん回す方法を書いていきます。
1. 子をDictionaryに突っ込む
今回行った対処としては、子要素はDictionaryで保持しておき、いつでも使える状態にします。
これは実際にコードを見てもらったほうが早いです。
public class ParentChild { private GameObject parent; private Dictionary<string, GameObject> children = new Dictionary<string, GameObject>(); public ParentChild() { this.parent = GameObject.Find("ParentObject"); Transform children = this.parent.transform; foreach (Transform child in children) { this.children[child.name] = child.gameObject; // ※1 } } }
これで子要素を取得できます。
(※1)のところでkeyを子GameObjectの名前にしていますが、これは普段職場でPHPを使用しているため、私は名称のほうが管理しやすいためです。このkeyについては、各々で管理しやすいものでいいかと思います。
2. Dictionaryの中身をforeachで取り出す
今回ネックになったのはこの工程です。
が、今の時代は便利ですね。Google検索で「unity dict」まで入れると、検索候補に「unity dictionary foreach」とありました。皆さん考えることは同じなんですね。(==;
foreachとDictionaryを絡ませる場合、取得先の型にGameObjectやTransformを入れると、「Cannot convert type 'System.Collections.Generic.KeyValuePair
ここに書いてあるまんまですが、Dictionaryをforeachで使う場合はKeyValuePair型でないといけません。そしてその中身として指定する引数も、取得元のDictionaryと合わせる必要があります。
これを前提としてコードを見ていきます。
public class ParentChild { private GameObject parent; private Dictionary<string, GameObject> children = new Dictionary<string, GameObject>(); public ParentChild() { this.parent = GameObject.Find("ParentObject"); Transform tmp = this.parent.transform; foreach (Transform child in tmp) { this.children[child.name] = child.gameObject; } foreach (KeyValuePair<string, GameObject> dic in this.children) { Debug.Log(dic.Value.name); } } }
これを実行すると、Console上にはParentObjectの下にあるGameObjectの名前がずらりと表示されたと思います。
最後に
この手法を取り入れていくと、ほとんど親子間のGameObject取得に困ることはないかと思います。
ただ懸念点としてあるのは、Dictionaryが果たしてどれくらい重いのか、GameObjectのデータをずっと保持しておくことでメモリをどれくらい食うのか、そこら辺がまだわかっていないです。
おそらくゲームがひととおり完成したとき、この周辺でメモリ問題が起きるかなーという不安はありますが、ひとまずはこれで作っていくことにします。
GameObjectの取得と管理は、この先も大きな課題のひとつとして出てきそうです。