質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

4268閲覧

[Unity]アクティブ・非アクティブにかかわらず、シーン(ヒエラルキー)上に存在する特定のコンポーネントを全て取得したい

ta93san

総合スコア23

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/03/04 01:37

やりたいこと

表題の通りです。アクティブ・非アクティブにかかわらず、シーン(ヒエラルキー)上に存在する特定のコンポーネントを全て取得したい。(Prefabなどシーン上に無いものは含まない)

Unityで任意のコンポーネントがアタッチされているGameObjectを取得する方法はいくつかありますが、表題の目的を満たすものがありません。
・GameObject.FindObjectsOfType<T>() → Activeなオブジェクトしか取得できない
・Resources.FindObjectsOfTypeAll(typeof(T)) → シーン(ヒエラルキー上)に無いPrefabまで取得されてしまう。

よろしくお願いいたします。

やってみたこと

① Resources.FindObjectsOfTypeAll(typeof(T))で(Prefabも含めて)全てのオブジェクトを取得し、オブジェクトがヒエラルキー上にあるかをhideFlagsで判定する方法。
こちらはエディター上でのシミュレーション時にはうまく動くのですが、ビルドするとPrefabのhideFlagsがシーン上のオブジェクトと同じNoneになり、判別ができなくなってしまいました。

C#

1using UnityEngine; 2using UnityEditor; 3using System.Collections.Generic; 4 5public static class Utils{ 6 public static List<T> FindObjectsOfAllInHierarchy<T>() where T : MonoBehaviour{ 7 var all_objs = Resources.FindObjectsOfTypeAll(typeof(T)) as T[]; 8 // hideFlagsでヒエラルキー上のオブジェクトを判別 9 List<T> components = all_objs.Where( c => (c.hideFlags != HideFlags.NotEditable) && (c.hideFlags != HideFlags.HideAndDontSave) && (c.hideFlags != HideFlags.HideInHierarchy) ).ToList(); 10 // 確認用の出力(Editor上で実行時はPrefabのhideFlagsはHideInHierarchyだったが、ビルド後はNoneになっていた。) 11 foreach(T obj in all_objs){ 12 Debug.Log("Name = "+obj.name+", Hide Flags = "+obj.hideFlags.ToString()); 13 } 14 return components; 15 } 16}

② Resources.FindObjectsOfTypeAll(typeof(T))で(Prefabも含めて)全てのオブジェクトを取得し、オブジェクトのパスから、シーンに取り込まれているか否かを判別する方法。
こちらはUnityEditor.GetAssetOrScenePath()を使ているので、Buildできません。(エディタ拡張用の機能なのかな?)

C#

1using UnityEngine; 2using UnityEditor; 3using System.Collections.Generic; 4 5public static class Utils{ 6 public static List<T> FindObjectsOfAllInHierarchy<T>() where T : MonoBehaviour{ 7 List<T> components = new List<T>(); 8 foreach (T obj in UnityEngine.Resources.FindObjectsOfTypeAll(typeof(T))) 9 { 10 // アセットからパスを取得.シーン上に存在するオブジェクトの場合,シーンファイル(.unity)のパスを取得. 11 string path = AssetDatabase.GetAssetOrScenePath(obj); 12 // シーン上に存在するオブジェクトかどうか文字列で判定. 13 bool isScene = path.Contains(".unity"); 14 // シーン上に存在するオブジェクトならば追加 15 if (isScene) 16 { 17 components.Add(obj); 18 } 19 } 20 return components; 21 } 22}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下のような書き方でどうでしょうか。
(例では取得するクラスはTransformにしていますが必要に応じて書き換えてください)

C#

1foreach (var obj in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects()) 2{ 3 foreach (var t in obj.GetComponentsInChildren<Transform>(true)) 4 { 5 Debug.Log(t.name); 6 } 7}

投稿2020/03/04 02:05

kawa0x0A

総合スコア271

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ta93san

2020/03/04 02:49

ありがとうございます。意図通りの動きをしています。解決いたしました。 GetRootGameObjects()は使ったことなかったです。確かにGetComponents()ならアクティブ非アクティブ関係なく取得できますね。 それにしてもhideFlagsで識別する方法はUnityの公式にも載されていた方法だったのですが、なぜビルドすると使えなくなってしまうのか。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問