nimanji’s blog

20代の最後は手のひらに楽しいゲームを産み落とす。それができるまでを記した日記。

親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の取得と管理は、この先も大きな課題のひとつとして出てきそうです。