(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

Hierarchy上の非アクティブなオブジェクトを検索し、取得する方法【Unity】


このエントリーをはてなブックマークに追加


この記事でのバージョン
Unity 2018.4.4f1


はじめに

GameObject.Findを使うとHierarchy上のオブジェクトを名前で検索する事ができますが、

(子に配置されているものだったら、transform.Findでも可)

//Targetという名前のGameObjectを検索し、取得(なければnull)
Debug.Log(GameObject.Find("Target"));
f:id:kan_kikuchi:20190810053030j:plain


残念ながら、アクティブじゃないオブジェクトは検索できません。

f:id:kan_kikuchi:20190810053122j:plain


という事で今回は、Hierarchy上の非アクティブなオブジェクトを検索し、取得する方法の紹介です!


なお、GameObject.Findしかり、こういう検索系の処理は重いので、

使い所を(出来るなら使わない方向で)考える必要がある点には注意が必要です。


ちなみに今回はプログラムで検索と取得をする方法ですが、

エディタ上でパッと見つけたい時には以下の記事の拡張が使えます。

f:id:kan_kikuchi:20210206064953g:plain




FindObjectsOfTypeAll

非アクティブなオブジェクトを検索し、取得したい場合は、

Resources.FindObjectsOfTypeAllを使います。


なお、FindObjectsOfTypeAllはオブジェクト名でなくタイプを指定して取得するので、

以下のようにGameObjectを全て取得し、その中から名前が一致するものを探す感じになります。

//GameObjectを全て取得
var gameObjectList = Resources.FindObjectsOfTypeAll<GameObject>();

//取得したGameObjectの中からTargetを探す
foreach (var go in gameObjectList) {
  if (go.name == "Target") {
    Debug.Log("ターゲット! : " + go);
  }
}
f:id:kan_kikuchi:20190811075036j:plain


ただし、エディタ上だとHierarchy上だけでなくProject上のPrefabも取得してしまいます。

f:id:kan_kikuchi:20190811075106j:plain


なので、AssetDatabase.GetAssetOrScenePathを使って

取得したものが、どこのものなのか判定する必要があります。

Debug.Log(AssetDatabase.GetAssetOrScenePath(gameObjectInHierarchy));
f:id:kan_kikuchi:20190811075900j:plain


なお、AssetDatabaseとそれを使うためのusing UnityEditorはエディタ上でしか使えないので、

UNITY_EDITORで囲む必要もあります。まとめると以下のような感じ。

#if UNITY_EDITOR
using UnityEditor; //AssetDatabaseを使うために必要
#endif
//GameObjectを全て取得
var gameObjectList = Resources.FindObjectsOfTypeAll<GameObject>();
    
//取得したGameObjectの中からTargetを探す
foreach (var gameObjectInHierarchy in gameObjectList) {
      
  #if UNITY_EDITOR
  //Hierarchy上のものでなければスルー
  if (!AssetDatabase.GetAssetOrScenePath(gameObjectInHierarchy).Contains(".unity")) {
    continue;
  }
  #endif
  
  if (gameObjectInHierarchy.name == "Target") {
    Debug.Log("ターゲット! : " + gameObjectInHierarchy);
  }
}
f:id:kan_kikuchi:20190811080026j:plain


ちなみにLINQを使って以下のように実装する事も可能です。

var target = Resources.FindObjectsOfTypeAll<GameObject>() //GameObjectを全て取得
#if UNITY_EDITOR
.Where(go => AssetDatabase.GetAssetOrScenePath(go).Contains(".unity")) //Hierarchy上のものだけ選別
#endif
.First(go => go.name == "Target"); //Targetという名前のものを取得