【Unity】FindやGetChildを使用せずに子オブジェクトを取得する方法

初めに

Unityでは子オブジェクトを取得する方法がいくつかあります。

最も楽に実装できる方法にFindやGetChildなどがありますが、これらはHierarchy上のGameObjectの名前や並び順に依存しており、時間が経った後や別の人が編集するといきなりエラーが発生して処理を見直すといったことがあります。

そのためFindやGetChildの使用は保守性の観点からできるだけ避けた方が良いように思います。

そこで、本記事ではFindやGetChildを使用せずに指定の子オブジェクトを取得する方法を紹介します。

取得方法

結論としては、取得対象のオブジェクトに独自のenum型の変数を持つクラスをアタッチし、親オブジェクトはGetComponetsInChildrenによりそのクラスを全て取得するといった方法でオブジェクトを取得します。

実装例

以下のような構成で、"ModelManager"クラスは各子オブジェクトが何の形状をしているかを知る必要がある場合を考えます。



オブジェクト判別用に独自のenum型の変数を持つクラスを作成し、取得対象のオブジェクトにアタッチします。

ModelTag.cs
~~~~~~~~~

using UnityEngine;

public enum MTag
{
    Cube,
    Sphere,
    Capsule,
}

public class ModelTag : MonoBehaviour
{
    public MTag mTag;
}



つぎに"ModelManager"に以下の処理を実装します。

ModelManager.cs
~~~~~~~~~

using UnityEngine;

public class ModelManager : MonoBehaviour
{
    private ModelTag[] models; 

    void Start()
    {
        // 子階層に付与されているModelTagコンポーネントを全て取得
        models = FindObjectsByType<ModelTag>(FindObjectsSortMode.None);

        // ModelTagおよび、GameObjectの参照例
        foreach (var model in models)
        {
            Debug.Log(model.mTag);
            Debug.Log(model.gameObject.transform.position);
        }
    }
}


これにより"ModelManager"クラスは子オブジェクトを取得することができます。 Hierarchy上の各GameObjectの名前を変更したり、並び順が変わったとしてもエラーは生じません。

最後に

今回はモデルの形状をenumとして設定しましたが、enumの値を変えれば何に対しても使用できます。

また、GetComponentsInChilderenではなく、FindObjectsByTypeとすると親子関係に関係なくシーン上の全ての"ModelTag"を持つオブジェクトを取得することもできます。