Buravo46's Note

学んだ事を書いていくブログです。

【Unity】Hierarchy上のゲームオブジェクトを全て取得

経緯

Hierarchy上のGameObjectを全て取得し、

そのGameObjectに対して色々したいEditorWindowを作るときに

必要になったので調べることにしました。

方法

Hierarchy上のGameObjectを全て取得する方法は2通りあります。

1通り目はActiveであるGameObjectの配列を返す

UnityEngine.Object.FindObjectsOfTypeです。

ですが、これはActiveであるGameObjectのみです。

2通り目はUnityオブジェクトとしてロードされているものを対象にTypeで指定した型の全てのオブジェクトの配列を返す

UnityEngine.Resources.FindObjectsOfTypeAllです。

これを使えば、ActiveでないGameObjectも取得することが可能です。

下記にこの2通りのサンプルスクリプトを記述しております。

Object.FindObjectsOfType

using UnityEngine;
using System.Collections;
/*===============================================================*/
/**
* ActiveであるGameObjectのみを取得するサンプル
* 2014年12月31日 Buravo
*/ 
public class Example : MonoBehaviour 
{
    /*===============================================================*/
    /**
    * @brief 最初に一度だけ実行されるメソッド
    */ 
    void Start () 
    {
        // typeで指定した型の全てのオブジェクトを配列で取得し,その要素数分繰り返す.
        foreach (GameObject obj in UnityEngine.Object.FindObjectsOfType(typeof(GameObject)))
        {
            // シーン上に存在するオブジェクトならば処理.
            if (obj.activeInHierarchy)
            {
                // GameObjectの名前を表示.
                Debug.Log(obj.name);
            }
        }
    }
    /*===============================================================*/
}
/*===============================================================*/

このスクリプトではFindObjectsOfTypeで取得した配列をforeach文で繰り返しています。

取得したGameObjectがシーンで有効であるかをactiveInHierarchyプロパティで調べています。

Resources.FindObjectsOfTypeAll

using UnityEngine;
using UnityEditor;
using System.Collections;
using System;
/*===============================================================*/
/**
* ActiveでないGameObjectも取得するサンプル
* 2014年12月31日 Buravo
*/ 
public class Example : MonoBehaviour 
{
    /*===============================================================*/
    /**
    * @brief 最初に一度だけ実行されるメソッド
    */ 
    void Start () 
    {
        // Typeで指定した型の全てのオブジェクトを配列で取得し,その要素数分繰り返す.
        foreach (GameObject obj in UnityEngine.Resources.FindObjectsOfTypeAll(typeof(GameObject)))
        {
            // アセットからパスを取得.シーン上に存在するオブジェクトの場合,シーンファイル(.unity)のパスを取得.
            string path = AssetDatabase.GetAssetOrScenePath(obj);
            // シーン上に存在するオブジェクトかどうか文字列で判定.
            bool isScene = path.Contains(".unity");
            // シーン上に存在するオブジェクトならば処理.
            if (isScene)
            {
                // GameObjectの名前を表示.
                Debug.Log(obj.name);
            }
        }
    }
    /*===============================================================*/
}
/*===============================================================*/

このスクリプトではFindObjectsOfTypeAll関数で取得した配列をforeach文で繰り返しています。

取得したGameObjectがシーン上に存在するオブジェクトかどうかを判断するために、

まずはAssetDatabase.GetAssetOrScenePath関数でアセットからパスを取得します。

これはシーン上に存在するオブジェクトの場合、シーンファイル(.unity)のパスが返されます。

この文字列が一致するかどうかをSystem.String.Contains関数を使用して判断し、

一致するならばシーン上に存在するオブジェクトとして処理しています。

まとめ

ActiveなオブジェクトのみならばObject.FindObjectsOfType

Activeでないオブジェクトも含めたいならばResources.FindObjectsOfTypeAll

場合に応じて使っていけばいいと思います。

参考サイト

Unity Editor上で動く自作ツールについて 〜 TIPS/豆知識を添えて 〜

Unityスクリプトリファレンス - Resources

Unityスクリプトリファレンス - Object

Unityスクリプトリファレンス - GameObject

Unityスクリプトリファレンス - AssetDatabase

文字列に特定の文字列が含まれているかを調べるには?(Contains編)