Sceneには何がある? GameObject一覧をC#から表示してみよう【Unity 6】
Unityでゲームを作っていると、HierarchyにはたくさんのGameObjectが並びます。
たとえば、
Main Camera
Player
Ground
Canvas
EventSystem
といったGameObjectです。
普段はHierarchyを見れば確認できますが、
「このSceneには、いったいどんなGameObjectが存在しているのだろう?」
ということを、C#から調べることもできます。
今回は、Sceneの中に存在するGameObjectをスクリプトから取得して一覧表示してみます。
さらに最後には、
Scene
├─ Player
│ ├─ Transform
│ ├─ SpriteRenderer
│ └─ Rigidbody2D
└─ Ground
├─ Transform
└─ BoxCollider2D
のように、
Scene → GameObject → Component
というUnityの構造まで確認してみましょう。
- 1. 1. UnityのSceneの中にはGameObjectがある
- 2. 2. Scene内のGameObjectを取得してみる
- 3. 3.
GameObject[]とは? - 4. 4.
FindObjectsSortMode.Noneとは? - 5. 5. 非アクティブなGameObjectはどうなる?
- 6. 6. 今いるSceneの名前も表示してみる
- 7. 7. Hierarchyと同じように親子関係も見てみたい
- 8. 8. SceneのGameObjectをHierarchy風に表示する
- 9. 9. さらにComponentまで表示してみよう
- 10. 10. Unityの画面とC#の処理を対応させる
- 11. 11.
FindObjectsByTypeとGetRootGameObjectsは何が違う? - 12. 12. 今回理解してほしいこと
- 13. まとめ
- 14. 関連記事
1. UnityのSceneの中にはGameObjectがある
まず、Unityの構造を簡単に整理します。
Sceneの中にはGameObjectがあります。
そしてGameObjectにはComponentが付いています。
イメージすると、
Scene
│
├─ GameObject
│ ├─ Component
│ ├─ Component
│ └─ Component
│
├─ GameObject
│ ├─ Component
│ └─ Component
│
└─ GameObject
という関係です。
普段Hierarchyで見ているのが、主にGameObjectです。
Inspectorを開いたときに並んでいる
- Transform
- Sprite Renderer
- Rigidbody 2D
- Box Collider 2D
- 自分で作ったスクリプト
などがComponentです。
[画像挿入位置1]
画像内容
Unityの基本構造を示す概念図。
Scene
↓
GameObject
↓
Component
複数のGameObjectがSceneに入り、それぞれに複数のComponentが付いている構図。
目的
これから取得する対象が、Unity全体のどの位置にあるのか理解してもらう。
構図
左または上にScene、その下に複数のGameObject、そのさらに下にComponent。
alt
UnityのScene、GameObject、Componentの関係を示した図
2. Scene内のGameObjectを取得してみる
まずは一番単純な方法です。
次のスクリプトを作ります。
using UnityEngine;
public class SceneObjectList : MonoBehaviour
{
void Start()
{
GameObject[] objects =
FindObjectsByType<GameObject>(FindObjectsSortMode.None);
foreach (GameObject obj in objects)
{
Debug.Log(obj.name);
}
}
}
このスクリプトを適当なGameObjectに付けて実行してみます。
Consoleには、たとえば次のように表示されます。
Main Camera
Player
Ground
Canvas
EventSystem
SceneObjectList
これで、
現在読み込まれているScene内からGameObjectを探して、その名前を表示
できました。
Unity 6では、オブジェクトを探すAPIとして FindObjectsByType が用意されています。
FindObjectsByType<GameObject>(FindObjectsSortMode.None);
ここでは、
GameObject
を探しているので、GameObjectの一覧が返ってきます。
3. GameObject[]とは?
今回、次のコードが出てきました。
GameObject[] objects;
[]が付いていることに注目してください。
これは、
GameObjectを複数まとめて入れる箱
だと考えると分かりやすいでしょう。
たとえばSceneに、
Player
Enemy
Ground
Main Camera
が存在していれば、
objects[0]
objects[1]
objects[2]
objects[3]
というように複数のGameObjectが格納されます。
そのため、
foreach (GameObject obj in objects)
を使って、一つずつ取り出しています。
4. FindObjectsSortMode.Noneとは?
次の部分も初めて見ると分かりにくいかもしれません。
FindObjectsSortMode.None
これは、
見つけたGameObjectを並べ替えなくてよい
という指定です。
Noneを指定した場合、Unityは結果を並べ替える処理を行いません。
そのぶん負荷を抑えられます。
ただし、表示されるGameObjectの順番は保証されません。
そのため、
Player
Main Camera
Ground
のように、Hierarchyと同じ順番になるとは限りません。
今回の目的は、
SceneにどんなGameObjectが存在するか確認する
ことなので、順番は特に問題ありません。
5. 非アクティブなGameObjectはどうなる?
Hierarchyでは、GameObjectのチェックを外して非アクティブにすることがあります。
たとえば、
Player
Enemy
SecretDoor ← 非アクティブ
Ground
というSceneを考えます。
通常の
FindObjectsByType<GameObject>(FindObjectsSortMode.None);
では、非アクティブなGameObjectは含まれません。
非アクティブなGameObjectも含めたい場合は、次のように書けます。
GameObject[] objects =
FindObjectsByType<GameObject>(
FindObjectsInactive.Include,
FindObjectsSortMode.None
);
これなら、非アクティブなGameObjectも対象になります。
Unity 6の FindObjectsByType では、FindObjectsInactive を指定して非アクティブなオブジェクトを含めるかどうか選択できます。
6. 今いるSceneの名前も表示してみる
せっかくなので、
どのSceneを調べているのか
も表示してみましょう。
その場合は、
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneObjectList : MonoBehaviour
{
void Start()
{
Scene scene = SceneManager.GetActiveScene();
Debug.Log("Scene : " + scene.name);
GameObject[] objects =
FindObjectsByType<GameObject>(FindObjectsSortMode.None);
foreach (GameObject obj in objects)
{
Debug.Log(obj.name);
}
}
}
と書けます。
SceneManager.GetActiveScene();
を使うと、現在アクティブになっているSceneを取得できます。
実行すると、
Scene : SampleScene
Main Camera
Player
Ground
Canvas
EventSystem
のように表示できます。
7. Hierarchyと同じように親子関係も見てみたい
ここまでの方法では、GameObjectの名前は分かります。
ただし、
Player
Weapon
Enemy
Main Camera
と表示されても、
Player
└─ Weapon
という親子関係までは分かりません。
UnityのHierarchyに近い形で表示したい場合は、Sceneの一番上にあるGameObjectから順番に調べる方法があります。
現在のSceneは、
SceneManager.GetActiveScene();
で取得できます。
そして、
scene.GetRootGameObjects();
を使うと、そのSceneに存在するルートGameObjectを取得できます。
ルートGameObjectとは、
親GameObjectを持っていない、一番上のGameObject
です。
たとえば、
Player
└─ Weapon
Enemy
Environment
├─ Ground
└─ Tree
なら、
Player
Enemy
Environment
がルートGameObjectです。
[画像挿入位置2]
画像内容
UnityのHierarchyを模した図。
SampleScene
├─ Player
│ └─ Weapon
├─ Enemy
└─ Environment
├─ Ground
└─ Tree
Player、Enemy、Environmentを「Root GameObject」として示す。
目的
Root GameObjectと子GameObjectの違いを視覚的に理解する。
構図
UnityのHierarchyに近い縦型ツリー。
alt
UnityのScene内のルートGameObjectと子GameObjectの関係
8. SceneのGameObjectをHierarchy風に表示する
では、少し発展させてみましょう。
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneHierarchyList : MonoBehaviour
{
void Start()
{
Scene scene = SceneManager.GetActiveScene();
Debug.Log("Scene : " + scene.name);
GameObject[] rootObjects = scene.GetRootGameObjects();
foreach (GameObject rootObject in rootObjects)
{
ShowGameObject(rootObject.transform, 0);
}
}
void ShowGameObject(Transform target, int depth)
{
string indent = new string(' ', depth * 2);
Debug.Log(indent + target.name);
foreach (Transform child in target)
{
ShowGameObject(child, depth + 1);
}
}
}
たとえばHierarchyが、
Player
├─ Weapon
└─ CameraTarget
Environment
├─ Ground
└─ Tree
なら、Consoleにも似た構造で表示できます。
Scene : SampleScene
Player
Weapon
CameraTarget
Environment
Ground
Tree
ここで行っていることは、
- Sceneの一番上のGameObjectを取得する
- GameObjectを表示する
- 子GameObjectを調べる
- さらにその子も調べる
という処理です。
これは再帰処理と呼ばれる書き方です。
ただし、今回は再帰そのものを理解することが目的ではありません。
まずは、
GameObjectの中に子GameObjectがあり、Scene全体が木のような構造になっている
ということが分かれば十分です。
9. さらにComponentまで表示してみよう
ここまで来たら、前回学習した GetComponents と組み合わせることができます。
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneHierarchyList : MonoBehaviour
{
void Start()
{
Scene scene = SceneManager.GetActiveScene();
Debug.Log("Scene : " + scene.name);
GameObject[] rootObjects = scene.GetRootGameObjects();
foreach (GameObject rootObject in rootObjects)
{
ShowGameObject(rootObject.transform, 0);
}
}
void ShowGameObject(Transform target, int depth)
{
string indent = new string(' ', depth * 2);
Debug.Log(indent + target.name);
Component[] components =
target.gameObject.GetComponents<Component>();
foreach (Component component in components)
{
Debug.Log(
indent +
" └ Component : " +
component.GetType().Name
);
}
foreach (Transform child in target)
{
ShowGameObject(child, depth + 1);
}
}
}
これを実行すると、たとえば、
Player
└ Component : Transform
└ Component : SpriteRenderer
└ Component : Rigidbody2D
└ Component : PlayerController
Ground
└ Component : Transform
└ Component : BoxCollider2D
のように表示できます。
ここまで来ると、
HierarchyとInspectorの情報をC#から読み取っている
ことが分かると思います。
GetComponents<Component>() は、指定したGameObjectに付いているComponentをまとめて取得しています。
10. Unityの画面とC#の処理を対応させる
普段Unity Editorでは、
Hierarchy
を見てGameObjectを確認し、
Inspector
を見てComponentを確認しています。
今回C#で行ったことを対応させると、
Hierarchy
↓
GameObjectを取得
Inspector
↓
GetComponents<Component>()
と考えることができます。
つまり、
Unity Editorが表示してくれている情報を、自分のプログラムから取得している
わけです。
[画像挿入位置3]
画像内容
左側にUnityのHierarchy、右側にInspector、その下または中央にC#コードを配置。
Hierarchy
↓
GameObject
Inspector
↓
Component
という対応を矢印で示す。
目的
Unity Editor上で普段見ている情報とC# APIを結び付ける。
構図
Hierarchy → GameObject取得、Inspector → GetComponents、という左右比較。
alt
UnityのHierarchyとInspectorをC#のGameObject取得とComponent取得に対応させた図
11. FindObjectsByTypeとGetRootGameObjectsは何が違う?
今回、GameObjectを調べる方法が2つ登場しました。
FindObjectsByType
FindObjectsByType<GameObject>(
FindObjectsSortMode.None
);
Scene内などからGameObjectを探してまとめて取得できます。
「どんなGameObjectが存在する?」
と簡単に調べたいときに分かりやすい方法です。
GetRootGameObjects
scene.GetRootGameObjects();
こちらはSceneの一番上にあるGameObjectを取得します。
そこから子GameObjectを順番にたどることで、
Scene
├─ Player
│ └─ Weapon
└─ Environment
├─ Ground
└─ Tree
というHierarchyの構造そのものを調べることができます。
今回のように、
UnityのScene構造を学習する
という目的なら、最終的には GetRootGameObjects() から親子をたどる方法のほうが、Unityの仕組みを理解しやすいでしょう。
12. 今回理解してほしいこと
今回、一番大切なのはAPI名を暗記することではありません。
UnityのSceneを、
Scene
│
├─ GameObject
│ ├─ Component
│ ├─ Component
│ └─ Component
│
└─ GameObject
├─ Component
└─ Component
という構造として考えられるようになることです。
普段Unity Editorで見ている、
Hierarchy
Inspector
も、実はこの構造を見やすく表示してくれているだけです。
C#から調べてみることで、
「Unityの画面に表示されているものには、ちゃんとプログラムからアクセスできる」
ということも見えてきます。
まとめ
今回はScene内のGameObjectをC#から調べてみました。
最初は、
FindObjectsByType<GameObject>(
FindObjectsSortMode.None
);
を使って、GameObjectの一覧を取得しました。
さらに、
SceneManager.GetActiveScene();
と、
scene.GetRootGameObjects();
を使うことで、Sceneの構造をHierarchyに近い形で調べることもできました。
そして最後に、
GetComponents<Component>();
を組み合わせることで、
Scene
↓
GameObject
↓
Component
までC#から確認できました。
Unityを学習するとき、
GameObjectとは何か
Componentとは何か
を言葉だけで覚えるより、
実際にUnity自身に「何を持っているの?」と聞いてみる
のも一つの学習方法です。
HierarchyとInspectorを見るだけだったUnityが、少し違って見えてくるかもしれません。
関連記事
前の記事では、1つのGameObjectにどんなComponentが付いているのかを調べました。
今回の記事は、その考え方を
1つのGameObject
↓
Scene全体
へ広げたものです。
学習順としては、
GameObjectを作る
↓
Componentを追加する
↓
GameObjectのComponentを調べる
↓
SceneのGameObjectを調べる
↓
Scene → GameObject → Componentを見る
と進めると、Unityの構造を整理しやすくなります。









ディスカッション
コメント一覧
まだ、コメントがありません