【Unity】複数のゲームオブジェクトやコンポーネントの取得
C#では、配列やListによってまとめて処理することができる仕組みが用意されています
もちろんUnityでもC#構文を使って実現できますが、UnityではGameObjectやComponentといった概念がありますのでそれを利用する方法を示します
サンプルシーン
GameObjectを取得してから処理
ヒエラルキーのルート下のルートゲームオブジェクトを全て取得(子オブジェクトを除く)
空のゲームオブジェクトを作成して、名前をサンプルシーンのように変更します
Managerオブジェクトに以下のスクリプトをアタッチします
using UnityEngine;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
void Start()
{
// アクティブなシーンを取得
Scene currentScene = SceneManager.GetActiveScene();
// シーン内のすべてのGameObjectを取得
GameObject[] allObjects = currentScene.GetRootGameObjects();
foreach (var obj in allObjects)
{
Debug.Log(obj.name);
}
}
}
Scene currentScene = SceneManager.GetActiveScene();
SceneManager.GetActiveScene()
メソッドを使用して、現在アクティブなシーンを取得しています。シーンはゲームの特定の場面やレベルを表します。
GameObject[] allObjects = currentScene.GetRootGameObjects();
currentScene.GetRootGameObjects()
メソッドを使用して、現在のシーン内のすべてのルートゲームオブジェクトを取得しています。ルートゲームオブジェクトはシーン内のヒエラルキーのトップレベルのオブジェクトを指します。
foreach (var obj in allObjects)
取得したすべてのゲームオブジェクトに対して、以下の処理を繰り返します。
Debug.Log(obj.name);
Debug.Log()
メソッドを使用して、各ゲームオブジェクトの名前をコンソールに出力します。デバッグ目的で使用されるため、実行中のゲームには直接的な影響はありません。
結果
全てのオブジェクが取得されました
Main Camera
Directional Light
Cat
Dog
Sparrow
Falcon
Manager
using UnityEngine;
public class Manager : MonoBehaviour
{
void Start()
{
GameObject[] objects = FindObjectsByType<GameObject>(FindObjectsSortMode.None);
foreach (var obj in objects)
{
Debug.Log(obj.name);
}
}
}
特定の基本クラスを継承している派生クラスへのアクセス(基本クラスのメソッド呼び出し)
各ゲームオブジェクトに同名のスクリプトをアタッチします
using UnityEngine;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
void Start()
{
// アクティブなシーンを取得
Scene currentScene = SceneManager.GetActiveScene();
// シーン内のすべてのGameObjectを取得
GameObject[] allObjects = currentScene.GetRootGameObjects();
foreach (var obj in allObjects)
{
obj.GetComponent<Animal>()?.Eat();
}
}
}
obj.GetComponent<Animal>()?.Eat();
各ゲームオブジェクトからAnimal
というコンポーネントを取得し、Eat()
メソッドを呼び出しています。GetComponent<Animal>()
メソッドは、指定したゲームオブジェクトがAnimal
コンポーネントを持っている場合はそのコンポーネントを返し、持っていない場合はnull
を返します。?.
演算子は、前の式がnull
である場合にはメソッド呼び出しをスキップするため、Animal
コンポーネントが存在しないゲームオブジェクトを無視します。
using UnityEngine;
public class Animal : MonoBehaviour
{
public void Eat()
{
Debug.Log(gameObject.name + "は、動物なので食べる");
}
}
public class Cat : Animal
{
}
public class Dog : Animal
{
}
public class Sparrow : Animal
{
}
public class Falcon : Animal
{
}
このコードの目的は、アクティブなシーン内のすべてのゲームオブジェクトからAnimal
コンポーネントを取得し、Eat()
メソッドを呼び出すことです。各ゲームオブジェクトがAnimal
を持っている場合にのみ食事の処理が行われます。このコードは、例えば動物のキャラクターを含むシーンで、すべての動物が食事をする必要がある場合に使用されます
全体のクラス図
結果
Animalクラスを継承しているコンポーネント(スクリプト)のみにアクセスして、メソッドが実行されます
FalconManagerCatは、動物なので食べる
Dogは、動物なので食べる
Sparrowは、動物なので食べる
Falconは、動物なので食べる
特定の基本クラスを継承している派生クラスへのアクセス(派生クラスのメソッド呼び出し)
各ゲームオブジェクトに同名のスクリプトをアタッチします
using UnityEngine;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
void Start()
{
// アクティブなシーンを取得
Scene currentScene = SceneManager.GetActiveScene();
// シーン内のすべてのGameObjectを取得
GameObject[] allObjects = currentScene.GetRootGameObjects();
foreach (var obj in allObjects)
{
obj.GetComponent<Animal>()?.MakeSounds();
}
}
}
obj.GetComponent<Animal>()?.MakeSounds();
各ゲームオブジェクトからAnimal
というコンポーネントを取得し、MakeSounds()
メソッドを呼び出しています。GetComponent<Animal>()
メソッドは、指定したゲームオブジェクトがAnimal
コンポーネントを持っている場合はそのコンポーネントを返し、持っていない場合はnull
を返します。?.
演算子は、前の式がnull
である場合にはメソッド呼び出しをスキップするため、Animal
コンポーネントが存在しないゲームオブジェクトを無視します
using UnityEngine;
public class Animal : MonoBehaviour
{
public virtual void MakeSounds()
{
}
}
using UnityEngine;
public class Cat : Animal
{
public override void MakeSounds()
{
Debug.Log("にゃー");
}
}
using UnityEngine;
public class Dog : Animal
{
public override void MakeSounds()
{
Debug.Log("わん");
}
}
using UnityEngine;
public class Sparrow : Animal
{
public override void MakeSounds()
{
Debug.Log("チュン");
}
}
using UnityEngine;
public class Falcon : Animal
{
public override void MakeSounds()
{
Debug.Log("キー");
}
}
このコードの目的は、アクティブなシーン内のすべてのゲームオブジェクトからAnimal
コンポーネントを取得し、Eat()
メソッドを呼び出すことです。各ゲームオブジェクトがAnimal
を持っている場合にのみ食事の処理が行われます。このコードは、例えば動物のキャラクターを含むシーンで、すべての動物が食事をする必要がある場合に使用されます
全体のクラス図
結果
Animalクラスを継承しているコンポーネント(スクリプト)のみにアクセスして、メソッドが実行されます
にゃー
わん
チュン
キー
特定の基本クラスを継承している派生クラスへのアクセス(派生クラスのメソッド呼び出し。抽象クラスを使う)
Animalクラス以外は同じになります
抽象クラスにし、また抽象メソッドを宣言することで、Animalクラスを継承している派生クラスにMakeSoundsメソッドを強制的に実装することを求めます(派生クラスにMakeSoundsメソッドが存在しないとエラーになります)
抽象メソッドは、実装を持ちません
using UnityEngine;
public abstract class Animal : MonoBehaviour
{
public abstract void MakeSounds();
}
public abstract void MakeSounds();
MakeSounds()
という名前の抽象メソッドを宣言しています。public
キーワードはアクセス修飾子で、このメソッドが外部からアクセス可能であることを示します。abstract
キーワードは、このメソッドが実装を持たず、派生クラスやインターフェースで実装されることを意味します。void
キーワードは、このメソッドが戻り値を返さないことを示します。
抽象メソッド MakeSounds()
の実装は、派生クラスや実装クラスによって提供される必要があることを示唆しています。具体的なクラスやインターフェースでこのメソッドをオーバーライドすることで、各クラスや実装に固有の音を生成するためのコードを提供することが期待されています
全体のクラス図
結果
Animalクラスを継承しているコンポーネント(スクリプト)のみにアクセスして、メソッドが実行されます
にゃー
わん
チュン
キー
特定のインターフェースを実装しているクラスへのアクセス(実装されたクラスのメソッド呼び出し)
各ゲームオブジェクトに同名のスクリプトをアタッチします
using UnityEngine;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
void Start()
{
// アクティブなシーンを取得
Scene currentScene = SceneManager.GetActiveScene();
// シーン内のすべてのGameObjectを取得
GameObject[] allObjects = currentScene.GetRootGameObjects();
foreach (var obj in allObjects)
{
obj.GetComponent<IFlyable>()?.Fly();
}
}
}
obj.GetComponent()?.Fly();
obj
という変数にアクセスし、そのゲームオブジェクトから IFlyable
というインターフェースを持つコンポーネントを取得します。GetComponent<IFlyable>()
メソッドは、指定したゲームオブジェクトが IFlyable
インターフェースを実装している場合はそのコンポーネントを返し、実装していない場合は null
を返します。
?.Fly();
: ?.
演算子を使用して、前の式の結果が null
でない場合に Fly()
メソッドを呼び出します。つまり、ゲームオブジェクトが IFlyable
インターフェースを実装している場合にのみ、Fly()
メソッドが呼び出されます。
using UnityEngine;
public class Cat : MonoBehaviour
{
}
using UnityEngine;
public class Dog : MonoBehaviour
{
}
using UnityEngine;
public class Sparrow : MonoBehaviour, IFlyable
{
public void Fly()
{
Debug.Log("スズメを飛ばす");
}
}
public class Sparrow : MonoBehaviour, IFlyable
Sparrow
という名前のクラスを定義しています。このクラスはIFlyable
インターフェースを実装していることを示しています。
IFlyable
インターフェースを実装したSparrow
クラスを定義し、スズメの飛行動作を制御するためのコードを提供することです。IFlyable
インターフェースの設定で飛行可能なオブジェクトやキャラクターにも同様のインターフェースが使用され、それぞれが異なる飛行動作を実装することができるようになります
using UnityEngine;
public class Falcon : MonoBehaviour, IFlyable
{
public void Fly()
{
Debug.Log("鷹を飛ばす");
}
}
全体のクラス図
結果
IFlyableクラスを実装しているコンポーネント(スクリプト)のみにアクセスして、メソッドが実行されます
スズメを飛ばす
鷹を飛ばす
全ての組み合わせ
実行結果
クリックしたオブジェクトごとに処理を分けるサンプルになります
using UnityEngine;
public class Manager : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonDown(0))
{
// クリック位置からRayを作成
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
// Rayがオブジェクトに衝突したかをチェック
if (Physics.Raycast(ray, out RaycastHit hit))
{
// 衝突したオブジェクトを取得
GameObject clickedObject = hit.collider.gameObject;
// 取得したオブジェクトに対する処理を実行
clickedObject.GetComponent<Animal>()?.MakeSounds();
clickedObject.GetComponent<IFlyable>()?.Fly();
}
}
}
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Camera.main
はシーン内のメインカメラを指します。ScreenPointToRay
メソッドは、マウスの位置からレイ(光線)を作成します。このレイは、マウスクリック位置からカメラの方向に伸びる仮想的な光線です。
if (Physics.Raycast(ray, out RaycastHit hit))
Physics.Raycast
メソッドは、作成したレイが他のオブジェクトと衝突したかどうかをチェックします。衝突がある場合、衝突したオブジェクトに関する情報がRaycastHit
オブジェクトに格納されます
GameObject clickedObject = hit.collider.gameObject;
RaycastHit
オブジェクトのcollider.gameObject
プロパティを使用して、衝突したオブジェクト自体を取得します
clickedObject.GetComponent<Animal>()?.MakeSounds();
衝突したオブジェクトが
Animal
コンポーネントを持っている場合、MakeSounds
メソッドを呼び出します。GetComponent
メソッドは、指定したコンポーネントの参照を取得します。?.
は、Animal
コンポーネントが存在しない場合にnull参照例外を回避するためのセーフナビゲーション演算子です
clickedObject.GetComponent<IFlyable>()?.Fly();
衝突したオブジェクトが
IFlyable
インターフェースを持っている場合、Fly
メソッドを呼び出します。インターフェースを持つオブジェクトは、飛行可能な動作を実装していることを意味します
このコードの主な目的は、マウスクリック時にオブジェクトとの衝突を検出し、衝突したオブジェクトに対して特定の処理を実行することです。例えば、Animal
コンポーネントがアタッチされているオブジェクトは音を鳴らし、IFlyable
インターフェースを実装しているオブジェクトは飛行します
全体のクラス図
直接コンポーネントを取得して処理
全てのゲームオブジェクトの全てのコンポーネント内から特定の基本クラスから継承している派生クラスを取得
コンポーネントを直接取得しています
using UnityEngine;
public class Manager : MonoBehaviour
{
void Start()
{
Animal[] animals = FindObjectsByType<Animal>(FindObjectsSortMode.None);
foreach (var animal in animals)
{
animal.Eat();
}
}
}
Animal[] animals = FindObjectsByType<Animal>(FindObjectsSortMode.None);
FindObjectsByType
メソッドを使用して、Animal
という型のオブジェクトを検索し、Animal
の配列であるanimals
変数に格納しています。FindObjectsSortMode.None
は、オブジェクトのソート方法を指定するための引数であり、ここではソートを行わないように指定しています。
ディスカッション
コメント一覧
まだ、コメントがありません