【学習】Unity で他のオブジェクトの機能を使う(Find と GetComponent の3ステップ)

広告

これまでの学習では、

  • Inspector で public 参照をつなぎ、オブジェクト同士を関連付ける方法

を体験しました。

一方で、ある GameObject に付いたスクリプトから、ほかの GameObject を動かしたり、そのオブジェクトの機能を使ったりする場面では、コードの中で「名前で探す」「コンポーネントを取り出す」というやり方もよく使います。今回は、その アクセスの流れを、3ステップに分けて整理します。


別の GameObject から操作したいとき

スクリプトが付いている自分ではなく、ほかの GameObject 側のコンポーネントを動かしたい、メソッドを呼び出したい、という場面は、学習の序盤でもよく出てきます。

たとえば次のような やりたいこと です。

  • 別オブジェクトの プレイヤー を動かしたい
  • 別オブジェクトの  にダメージを与えたい(相手のスクリプトのメソッドを呼び出す)
  • 別オブジェクトの カメラ を操作したい

こういうときに必要になるのが、ほかのオブジェクト(箱)にどうたどり着くかという アクセス の考え方です。今回は、とてもシンプルに説明します。


Unity は「箱」と「中身」でできている

まず一番大事な考え方です。

Unity はおおまかに次のように整理できます。

  • GameObject(箱) … シーン上に存在するものすべて
  • Component(中身・機能) … 箱に取り付ける機能

たとえば次のようなイメージです。

Player(箱)
 ├ Transform(位置・回転・大きさ)※最初から付いている
 ├ Rigidbody(物理)
 └ PlayerScript(自分で作った機能)

Transform は、すべての GameObject に最初から付いています。自分で追加する必要はありません。


やることはたった3つ

Unity で他のオブジェクトの機能を使うときは、基本的に次の順番です。

  1. 相手の箱を見つける(例:GameObject.Find()
  2. 中身(機能)を取り出すGetComponent<>()
  3. その機能を使う

これだけです。

Unity では、多くの場合 「箱(GameObject)→ 中身(Component)」 の順でアクセスします。


この記事のサンプルを試すとき(シーンの準備)

この記事のサンプルを試すとき(シーンの準備)

プロジェクトがまだない場合は、Unity のインストールとプロジェクト作成 を先に進めてください。

今回は、たとえば3Dで作成した「FindAndGetComponentSample」プロジェクトとして進めていきましょう

次のように Hierarchy を用意すると、後ろのコード例がそのまま試せます。

  1. Player
    • GameObject を作成し、名前を Player にする(Find("Player") と 完全一致)。 
    • Add Component で Rigidbody を付ける(コードが GetComponent<Rigidbody>() なので必須)。 
    • Rigidbody の Use Gravity は オフ にする。床を置かない簡易シーンでは、オンだと 下方向に落ち続けるため、動きの確認がしづらくなります。
  2. SampleScript を付けるオブジェクト
    • 別名の GameObject(例: Sample)を1つ作る。 
    • SampleScript を作成し、このオブジェクトに アタッチする。 
    • Player には付けない(別オブジェクトから Player を探す流れのため)。

補足: プレイヤー自身の動きだけを書くときは、多くの場合 スクリプトを Player に付け、同じ GameObject から GetComponent<Rigidbody>() する書き方がよく使われます。今回は ほかのオブジェクトから Player を探す練習 のため、わざと別の GameObject にスクリプトを付けています。

名前の typo や Rigidbody の未追加だと Find / GetComponent が null になり、実行時エラーになることがあります。

Playerゲームオブジェクト

Sampleゲームオブジェクト


ステップ① 相手の箱を見つける

Playerゲームオブジェクトを見つける

GameObject player = GameObject.Find("Player");

まずは相手を見つけます。

"Player" という名前のオブジェクトを、シーン全体から探します。


ステップ② 中身(機能)を取り出す

Rigidbodyコンポーネントを取り出す

Rigidbody rb = player.GetComponent<Rigidbody>();

次に、その箱の中に入っている機能を取り出します。

< > の中に、取り出したい Component の型名を書きます。


ステップ③ 機能を使う

RididbodyクラスのAddForceメソッドを呼び出す

public class Rigidbody : Component
{    
    public void AddForce(Vector3 force)
    {
        // 力を加える機能が記述されています
    }
}

SampleScriptコードで、次の操作をすることによって内部コードを見ることができます

rb.AddForce(Vector3.forward * 5f);

取り出した機能を使います。これで前方向に力を加えることができます。


3ステップをまとめて書くとこうなる

実際のコードは、クラス全体では次のように書けます。

using UnityEngine;

public class SampleScript : MonoBehaviour
{
    // ② で取り出した機能を他のメソッドでも使えるよう、フィールドに宣言する
    private Rigidbody rb;

    void Start()
    {
        // ① 箱を見つける
        GameObject player = GameObject.Find("Player");

        // ② 機能を取り出してフィールドに保存する
        rb = player.GetComponent<Rigidbody>();
    }

    // Rigidbodyを触るなら「迷ったら FixedUpdate」
    void FixedUpdate()
    {
        // ③ 機能を使う(Update でも rb を参照できる)
        rb.AddForce(Vector3.forward * 5f);
    }
}

Start() で取得した結果をフィールドに保存することで、Update() など他のメソッドからも rb を使い回せます。

(上の「シーンの準備」の補足どおり、自分の Rigidbody だけを扱うなら Player にスクリプトを付け、Find を使わず GetComponent<Rigidbody>() だけで足りることも多いです。)


GameObject.Find を使うときの注意点

今回使った GameObject.Find() は、名前でオブジェクトを探すメソッドです。

わかりやすいので最初の学習向きですが、毎フレーム呼び出すと処理が重くなりやすいです。

そのため、次のように使うことが多いです。

  • Start() などで 1回だけ 使う
  • 結果を フィールドに保存 して使い回す

今はまず 「どうやってアクセスするか」 の流れを掴むことが大切です。慣れてきたら、より効率的な方法も学んでいきましょう。


まとめ

Unity では、他のオブジェクトの機能を使うときは、基本的に次の流れになります。

  1. 見つける(例:GameObject.Find()
  2. 取り出すGetComponent<>()
  3. 使う(取り出した変数を操作する)

「箱の中に機能が入っている」 という構造を意識するだけで、Unity のコードがぐっと読みやすくなります。


関連記事

訪問数 19 回, 今日の訪問数 19回

広告

Unity

Posted by hidepon