【Unity】Find関数とは?他のオブジェクトを探してくれるメソッド

Find関数とは?オブジェクト探し Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのFind関数ってなに?」

「Find関数ってどうやって使えばいいの?」

というお悩みの方に向けた内容となっています。

Find関数とは、Unityでオブジェクトを探す際に使うメソッドです。

スクリプトで、アタッチしていない別のオブジェクトに対して、処理を行ったり情報を取得する際は、そのオブジェクトを取得して参照できる状態にする必要があります。

このオブジェクトの取得方法には、様々な方法がありますが、その中でもFind関数直接オブジェクト名を指定して、オブジェクト情報を取得することができるメソッドになっています。

そこで、このページでは、Unityでオブジェクトを探す際に使用するFind関数について、どんな関数なのか、使い方や注意点をまとめていきます。

なお、このページでは、

Windows11
Unity Hub3.11.1
Unity6

のバージョンで解説しています。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Find関数とは?他のオブジェクトを探して情報を取得できるメソッド

Find関数は、オブジェクトを探してその情報を取得することができるメソッドになっています。

例えば、オブジェクトの座標を取得したい場合、transform.positionという変数を使ってそのオブジェクトの座標を取得することができます。

ただ、そのオブジェクトに直接スクリプトをアタッチしていない場合は、どのオブジェクトの座標を取得するのか、transform.positionの前にオブジェクトを指定してあげる必要があります。

この指定するオブジェクトは、何かしらの方法でそのオブジェクトを取得する必要がありますが、Find関数を使うと、直接オブジェクト名を使ってオブジェクトを探し、情報を取得することで、座標などが分かるようになります。

このように、Find関数は別のオブジェクトの情報を参照したい場合に、使うことができるメソッドです。

Find関数の使い方

Find関数には、

という2つがあり、オブジェクトを探す検索対象戻り値の型に違いがあります。

ここでは、GameObject.FindTransform.Findのそれぞれの使い方と違いについてまとめていきます。

GameObject.Find

GameObject.Findは、検索対象のオブジェクトが全体、かつアクティブなオブジェクトのみが対象範囲となっています。

GameObject.Findの使い方

GameObject.Findを使う際は、引数オブジェクト名を文字列で渡してあげることで、そのオブジェクトを探すことができます。

GameObject.Find("オブジェクト名");

なお、GameObject.Findで返ってくる値は、GameObject型となります。

例えば、playerというオブジェクトの座標を別のスクリプトで取得したい場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        GameObject player = GameObject.Find("player");  // playerのオブジェクトを取得
        Debug.Log(player.transform.position);   // playerの座標を表示する
    }
}

7行目でGameObject.Findを使ってオブジェクトを取得して、player変数に代入することで、そのオブジェクトの座標を取得することができています。

GameObject.Findは検索対象がシーン全体

GameObject.Findで探すことができるオブジェクトは、シーン全体のオブジェクトとなっています。

具体的には、ヒエラルキーウィンドウに表示されているシーン配下のオブジェクトのすべてが検索対象となっています。

この中から、オブジェクト名を引数で指定することで、そのオブジェクトの情報を取得することができます。

GameObject.Findはアクティブ状態のみ探せる

GameObject.Findを使う際に気を付けるべきポイントが、アクティブ状態のオブジェクトしか対象範囲には入っていない点です。

オブジェクトのアクティブ状態非アクティブ状態は、スイッチのオンオフのようなもので、非アクティブにするとオブジェクトが表示されなくなり、アタッチされているスクリプトやコンポーネントも使えなくなります。

この非アクティブとなっているオブジェクトは、GameObject.Findで検索対象に入らず探すことはできません。

例えば、アクティブ状態のplayerAと、非アクティブ状態のplayerBというオブジェクトが配置してあった場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        GameObject playerA = GameObject.Find("playerA");  // playerAのオブジェクトを取得
        GameObject playerB = GameObject.Find("playerB");  // playerBのオブジェクトを取得
        Debug.Log(playerA.transform.position);   // playerAの座標を表示する
        Debug.Log(playerB.transform.position);   // playerBの座標を表示する
    }

}

それぞれの座標を取得しようとした場合、playerBは非アクティブ状態なので、オブジェクト情報を取得することができず、エラーが表示されます。

特に、SetActive関数でオブジェクトのオンオフを行っている場合に、GameObject.Findを使う際は気を付けておきましょう。

Transform.Find

Transform.Findは、GameObject.Findよりも検索対象が小さく、子オブジェクトを対象範囲としています。

Transform.Findの使い方

Transform.Findの使い方は、GameObject.Findと似ていて引数にオブジェクト名を渡してあげることで、子オブジェクトの中からそのオブジェクトを探してくれます。

transform.Find("子のオブジェクト名");

この時、Transformの記載は小文字で「transform」となるため、注意しておきましょう。

また、Transform.Findでの戻り値はTransform型となっているため、GameObjectを取得する際は、

transform.Find("子のオブジェクト名").gameObject;

と書いてあげる必要があります。

例えば、子オブジェクトのchildPlayerの座標を取得したい場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        Transform childPlayer = transform.Find("childPlayer");  // childPlayerのオブジェクトを取得
        Debug.Log(childPlayer.position);   // childPlayerの座標を表示する
    }
}

と書いてあげることで、このスクリプトがアタッチされているオブジェクトの子オブジェクトのみを対象にしてchildPlayerを探すことができ、座標を表示することができます。

Transform.Findは検索対象が子オブジェクトのみ

これまでも記載してきましたが、Transform.Findの検索対象の範囲は子オブジェクトのみとなっています。

具体的には、ヒエラルキーウィンドウでスクリプトをアタッチしているオブジェクトの子オブジェクトのみが対象範囲となっています。

そのため、Transform.FindはGameObject.Findよりも検索対象が狭くなっています。

Transform.Findは非アクティブ状態も探せる

Transform.Findは、GameObject.Findと違って非アクティブのオブジェクトも探すことができます。

実際に、同じ親オブジェクトに入っているアクティブ状態playerAと、非アクティブ状態playerBというオブジェクトがあり、親オブジェクトに対して以下のスクリプトをアタッチした場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        Transform playerA = transform.Find("playerA");  // playerAのオブジェクトを取得
        Debug.Log(playerA.position);   // playerAの座標を表示する
        Transform playerB = transform.Find("playerB");  // playerBのオブジェクトを取得
        Debug.Log(playerB.position);   // playerBの座標を表示する
    }
}

どちらのオブジェクトの情報も取得することができています。

そのため、非アクティブのオブジェクトを取得したい場合には、GameObject.FindではなくTransform.Findを使うことで実現することができます。

Find関数の注意点:負荷が大きいので使い過ぎに注意

Find関数は、直接オブジェクト名を使って検索することになるので、非常に負荷が大きい処理が行われています。

そのため、使いすぎるとゲームがかくかくしたり、重たくなる現象が起きる場合があります。

特に、GameObject.Findは、すべてのオブジェクトを対象にしているため、Updateメソッドで毎フレーム読み込むなどの使い方は負荷が大きすぎるので、やめるようにしておきましょう。

もし、Find関数で何度も処理を行うという際は、検索対象が絞られているTransform.Findを使うか、インスペクターウィンドウからオブジェクトを参照する方法を使っていくようにしましょう。

まとめ

このページでは、Unityでオブジェクトを参照するのに使うFind関数についてまとめていきましたが、いかがでしたでしょうか?

Find関数には、GameObject.FindTransform.Findの2つがあり、検索対象と戻り値の型に違いがありました。

基本的には、Find関数は負荷が大きい処理なので、Startメソッド内で使うかTransform.Findでオブジェクトを参照するような使い方をしましょう。

また、Findを使わなくても、インスペクターウィンドウで直接オブジェクト情報をドラッグ&ドロップして渡す方法もあるので、無理にFind関数は使わなくても良いでしょう。

最後までお読みいただきまして、ありがとうございました!

コメント