1. はじめに
Unityでゲームを作っていると、「特定のスクリプトがついているオブジェクトだけを一括で取得したい」という場面に遭遇することがあります。例えば、敵キャラクターやアイテムなど、共通の処理が必要なオブジェクトをまとめて管理したい場合です。
これを手動でやろうとすると、オブジェクトの名前やタグを個別に指定したり、ひとつひとつ確認したりと大変ですよね。でも、Unityには便利な機能が用意されていて、これを簡単に実現できます。それが FindObjectsOfType<>()
というメソッドです。
初心者でも簡単に理解できるように、わかりやすく解説しますので安心してください!この方法を覚えれば、オブジェクト管理が一気にラクになります。
今回は基本的なコードの書き方をご紹介しますが、もしもっと効率的に開発を進めたい方には、有料アセットを使う方法もおすすめです。そのひとつが 「Odin Inspector」です。簡単にプロジェクトを整理し、作業時間を短縮できます。
2. Cubeの作成とスクリプトの追加
ここでは、Unityの基本操作を使って「Cubeオブジェクト」を作成し、それにスクリプトを追加する手順を説明します。これが後で他のCubeと一緒に管理される基本になります。
1. Cubeを作成する
- ヒエラルキーウィンドウで右クリック
- Unityの画面左上にある「ヒエラルキー」ウィンドウを探します。
- その中で右クリックするとメニューが表示されます。
- 「3D Object」→「Cube」を選択
- メニューから「3D Object」にカーソルを合わせ、「Cube」を選択します。
- 作成されたCubeを確認
- ヒエラルキーに「Cube」という名前のオブジェクトが追加されます。
2. スクリプトを作成してCubeに追加する
次に、CheckObject
という名前のスクリプトを作成し、Cubeにアタッチします。
- プロジェクトウィンドウでスクリプトを作成
- Unity画面下部にある「プロジェクトウィンドウ」で空白部分を右クリックします。
- 「Create」→「C# Script」を選択します。
- スクリプトの名前を「CheckObject.cs」に変更します。
- このスクリプトは特に機能を持たせません。このクラスがオブジェクトを検索するための印になります。
- スクリプトをCubeに追加
- ヒエラルキーで作成したCubeをクリックして選択します。
- プロジェクトウィンドウで作成した
CheckObject.cs
をクリックしてドラッグします。 - Cubeにドラッグ&ドロップすると、インスペクターに
CheckObject
が表示されます。
- 確認
- Cubeを選択した状態でインスペクターウィンドウを開きます。
- 「Check Object (Script)」という項目が表示されていれば、スクリプトが正しく追加されています。
これで、Cubeが「CheckObject.cs」を持つ状態が完成しました!この後、複製したCubeにも同じスクリプトが追加されるので、準備はバッチリです。次のステップでは、このCubeを複製して増やしていきましょう!
3. Cubeを複製する
次に、先ほど作成した Cube を複製してみましょう。同じようなオブジェクトをたくさん作るときに、この「複製」機能はとても便利です。今回は、複数のCubeに同じスクリプト(CheckObject.cs
)が付いている状態を作ります。
Cubeを複製する方法
- ヒエラルキーでCubeを選択する
まず、ヒエラルキーウィンドウで、先ほど作成したCubeをクリックして選択します。 - 複製する
Cubeを選択した状態で、次のどちらかの方法を使って複製します:- ショートカットキーを使う方法
WindowsではCtrl + D
、MacではCmd + D
を押すと、Cubeが複製されます。 - 右クリックメニューを使う方法
ヒエラルキーでCubeを右クリックして「Duplicate」を選びます。
- ショートカットキーを使う方法
- 複製されたCubeを確認する
ヒエラルキーに「Cube (1)」や「Cube (2)」のような名前で新しいCubeが表示されます。 - 複製を繰り返す
必要な個数だけ複製します。例えば、5個のCubeを作りたい場合は、同じ操作をあと4回繰り返します。
注意点
- 複製したCubeには、元のCubeと同じ設定やスクリプト(
CheckObject.cs
)が引き継がれています。これで、すべてのCubeにスクリプトが付いている状態になります。 - 複製したCubeの位置が重なってしまうと見えづらくなるので、それぞれ少しずらして配置しておきましょう。
位置を調整する方法
- 複製したCubeをヒエラルキーでクリックして選択します。
- シーンビューでCubeをドラッグして位置を変更します。
- 位置を正確に調整したい場合は、「インスペクター」ウィンドウで
Transform
のPosition
の値を直接変更します。例えば、X
を1ずつ増やすと、Cubeが横一列に並びます。
これで、同じスクリプトがアタッチされた複数のCubeを作る準備が整いました!
4. 空のオブジェクトを作成
「空のオブジェクト」は、ゲーム内で特定のスクリプトやシステムを管理するための目に見えないオブジェクトです。ここでは、作成したCubeを管理し、スクリプトでそれらをまとめて取得するための「空のオブジェクト」を作成します。
空のオブジェクトの作り方
- 右クリックでメニューを表示
- ヒエラルキーウィンドウの空白部分で右クリックします。
- Create Emptyを選択
- メニューの中から「Create Empty」(空のオブジェクトを作成)をクリックします。
- これで新しい空のオブジェクトがヒエラルキーに追加されます。
補足
空のオブジェクト自体はゲーム内で見えませんが、スクリプトを管理するのに便利です。今回は、この空のオブジェクトに FindObject.cs
をアタッチして、特定のスクリプトを持つCubeをすべて管理する仕組みを作ります。
5. FindObject.csを作成してスクリプトを記述する
ここでは、空のオブジェクトに追加するスクリプト FindObject.cs を作成して、特定のクラスを持つオブジェクトを一括で取得する仕組みを実装します。
スクリプト作成の手順
- スクリプトを作成
- プロジェクトウィンドウ(Assetsフォルダ)を右クリックします。
- 「Create」→「C# Script」を選択。
- 作成されたスクリプトに「FindObject」という名前を付けます。
- FindObjectスクリプトを記述
- 作成したスクリプトをダブルクリックして開きます。
- 以下のコードを入力します:
using
宣言- UnityEngine: Unityの基本的な機能を使うために必要です。たとえば、
MonoBehaviour
やDebug.Log
などを使うためにこれが必要です。 - System.Collections と System.Collections.Generic: 配列やリストなどのコレクションを扱うときに使いますが、今回のスクリプトでは特に重要な役割はありません。
- UnityEngine: Unityの基本的な機能を使うために必要です。たとえば、
- クラスの定義とプロパティ
public class FindObject : MonoBehaviour
- このスクリプトは「ゲームオブジェクトにアタッチして使うクラス」です。
MonoBehaviour
を継承しているので、Unityの特別な機能(例:Start
やUpdate
)を使えます。
- このスクリプトは「ゲームオブジェクトにアタッチして使うクラス」です。
public CheckObject[] Objects;
- 配列(Array): 「シーン内にある全ての
CheckObject
を入れる箱」のようなものです。 public
: Unityエディター上で、この配列を確認できるようにしています。
- 配列(Array): 「シーン内にある全ての
- Start メソッド
void Start()
- シーンが始まったときに一度だけ呼び出されます。
FindObjectsOfType<CheckObject>()
- シーン内にある全ての
CheckObject
クラスがアタッチされたオブジェクトを探して、配列に入れる機能です。
- シーン内にある全ての
Objects =
- 探してきたオブジェクトを
Objects
配列に保存しています。
- 探してきたオブジェクトを
Debug.Log
- コンソールにメッセージを表示します。ここでは、
Objects.Length
を使って、見つけたオブジェクトの「数」を表示しています。
- コンソールにメッセージを表示します。ここでは、
スクリプトの全体的な動き
- ゲームが始まると、
Start
メソッドが呼ばれます。 - シーン内にある
CheckObject
クラスを持つ全てのオブジェクトを探し、Objects
という配列にまとめます。 - 最後に、その配列に入っているオブジェクトの数をコンソールに表示します。
注意点
CheckObject
クラス- このスクリプトには登場しませんが、別の場所で作られている「スクリプト」です。探す対象になるため、この名前を間違えないように注意してください。
FindObjectsOfType<T>()
の処理負荷- シーン内のオブジェクトを全部チェックするので、大量のオブジェクトがある場合、処理が重くなることがあります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FindObject : MonoBehaviour
{
// CheckObject クラスが付いているオブジェクトを格納する配列
public CheckObject[] Objects;
void Start()
{
// FindObjectsOfType<CheckObject>() を使って、シーン内のすべての CheckObject を取得
Objects = FindObjectsOfType<CheckObject>();
// 配列に格納されたオブジェクトの数をコンソールに表示
Debug.Log("CheckObjectがアタッチされたオブジェクトの数: " + Objects.Length);
}
}
- スクリプトの説明
public CheckObject[] Objects;
- この配列に
CheckObject
クラスが付いているすべてのオブジェクトを格納します。
- この配列に
FindObjectsOfType<CheckObject>()
- シーン内に存在するすべての
CheckObject
クラスを持つオブジェクトを取得します。
- シーン内に存在するすべての
Debug.Log
- 配列に格納されたオブジェクトの数を確認するため、Unityのコンソールに出力します。
- スクリプトを空のオブジェクトにアタッチ
- ヒエラルキーで空のオブジェクト「Manager」を選択します。
- 作成した
FindObject.cs
を「Manager」にドラッグ&ドロップしてアタッチします。
6. 動作確認: ゲームを実行してみる
さあ、ここまででスクリプトやオブジェクトの準備が完了しました!最後に、実際にゲームを再生して、 FindObject
スクリプトが正しく動作するかを確認しましょう。
ゲームを実行する方法
- Unityエディターの上部にある再生ボタン(▶マーク)をクリックしてゲームをスタートします。
- 画面では特に何も表示されませんが、インスペクター画面から配列を確認できます。
この基本的なコードはシンプルですが、プロジェクトが大きくなると管理が大変になることも。そういうときに 「Odin Inspector」 を使えば、スクリプトだけでなくエディター全体がさらに便利になります。
例えば、以下のようなインスペクター画面を簡単に作成できます:
- リスト内のオブジェクトをクリックすると、自動でシーン上で選択。
- 必要なデータだけをピックアップして表示。
- 自作ツールを追加して、Unity内での操作を効率化。
こういった機能を使うと、開発のスピードが一気に上がります。
7. まとめ
この記事では、Unityで特定のスクリプトがアタッチされているオブジェクトを一括で取得して配列に格納する方法を解説しました。この方法を使えば、例えばゲーム内のターゲットや特定の属性を持つオブジェクトを簡単に管理できるようになります。
以下の手順を通して、初心者でも簡単に実現できることが分かりました:
- 基本となるCubeの作成。
- スクリプトを作成し、オブジェクトにアタッチ。
- 空のオブジェクトを使って管理スクリプトを実行。
最終的に、FindObjectsOfType
を活用することで、同じスクリプトがアタッチされたオブジェクトをすべて取得できる仕組みが完成しました。この手法は、ゲーム開発で頻繁に使われる便利なテクニックです。ぜひ活用してみてください!
よくある質問
- QQ1: この方法で取得できるオブジェクトに条件をつけることはできますか?
- A
はい、取得した配列をループで回して、
tag
や名前 (name
) を条件にフィルタリングすることができます。例えば、if (object.tag == "Target")
という条件を使うことで特定のタグを持つオブジェクトだけを絞り込めます。
- Q
FindObjectsOfType
はどんな場合に使うべきですか? - A
ゲーム開始時に一度だけ全オブジェクトを収集する場合に便利です。ただし、大量のオブジェクトをリアルタイムで収集するのには向いていないため、その場合はオブジェクトをリストに追加・削除する仕組みを用意した方が良いです。
- Q配列ではなくリストにしたい場合はどうすれば良いですか?
- A
配列をリストに変換することが可能です。以下のようにコードを変更してみてください:
using System.Linq; void Start() { List<CheckObject> objectList = FindObjectsOfType<CheckObject>().ToList(); }