Unityで別のゲームオブジェクトのスクリプトにアクセスする方法

はじめに

Unityでゲームを作るとき、あるゲームオブジェクトのスクリプトから、別のゲームオブジェクトのスクリプトにアクセスしたいことがよくあります。
例えば、「プレイヤーのHPを管理するスクリプト」に「敵のスクリプト」からアクセスして、ダメージを与えるといったケースです。

このチュートリアルでは、基本的な方法から実践的な方法まで、わかりやすく解説していきます!


1. GameObject.Find を使う方法

どんなときに使う?

  • シーン内に 必ず1つだけ存在するオブジェクト にアクセスしたいとき。
  • ゲームの 開始時(StartAwake に1回だけ取得する場合。

コード

1.1. 準備

まず、対象となる2つのオブジェクトを用意します。

① プレイヤー側(Playerオブジェクトにアタッチ)

using UnityEngine;

public class Player : MonoBehaviour
{
    public int health = 100;  // HP

    public void TakeDamage(int damage)
    {
        health -= damage;
        Debug.Log("プレイヤーの残りHP: " + health);
    }
}

② 敵側(Enemyオブジェクトにアタッチ)

using UnityEngine;

public class Enemy : MonoBehaviour
{
    void Start()
    {
        GameObject playerObject = GameObject.Find("Player");  // "Player" という名前のオブジェクトを探す

        if (playerObject != null)
        {
            Player playerScript = playerObject.GetComponent<Player>();  // Playerスクリプトを取得
            playerScript.TakeDamage(10);  // 10ダメージを与える
        }
    }
}

ポイント

GameObject.Find("オブジェクト名") でシーン内のオブジェクトを検索
GetComponent<スクリプト名>() でスクリプトを取得

注意点

⚠️ 毎フレーム Find を使うとパフォーマンスが悪くなるStart などで 1回だけ 使うのが良い。


2. GameObject.FindWithTag を使う方法

どんなときに使う?

  • Find だと 名前を変えると取得できなくなるタグを使えば名前が変わっても大丈夫!
  • プレイヤーが複数シーンで共通 する場合、タグで検索すると便利。

コード

1.1. タグの設定

  1. Playerオブジェクトを選択
  2. Inspectorウィンドウ → 「Tag」 → 「Add Tag…」をクリック
  3. 「+」ボタンを押して「PlayerTag」を追加
  4. Playerオブジェクトのタグを「PlayerTag」に変更

1.2. FindWithTag を使う

GameObject playerObject = GameObject.FindWithTag("PlayerTag");
if (playerObject != null)
{
    Player playerScript = playerObject.GetComponent<Player>();
    playerScript.TakeDamage(10);
}

メリット

名前を変更しても検索可能(タグで識別するため)
Find よりも 管理しやすい

デメリット

⚠️ タグを設定しないと機能しない


3. SerializeField で手動設定(おすすめ!)

どんなときに使う?

  • 最もパフォーマンスが良く、安定した方法
  • Inspector でドラッグ & ドロップするだけ!

コード

3.1. 敵側(Enemyオブジェクトにアタッチ)

using UnityEngine;

public class Enemy : MonoBehaviour
{
    [SerializeField] private Player player;  // Inspector で設定できる変数

    void Start()
    {
        if (player != null)
        {
            player.TakeDamage(10);
        }
    }
}

3.2. Inspectorで設定

  1. Enemyオブジェクトを選択
  2. Inspectorで「Player」フィールドが表示される
  3. シーン内のPlayerオブジェクトをドラッグしてセット!

メリット

パフォーマンスが良い!(毎回検索しないので高速)
オブジェクト名やタグを気にしなくて良い

デメリット

⚠️ 手動でInspectorにセットする手間がある


4. GetComponentInChildren / GetComponentInParent を使う

どんなときに使う?

  • 親子関係があるオブジェクトのスクリプトを取得する場合

コード

4.1. 子オブジェクトのスクリプトにアクセス

Player playerScript = GetComponentInChildren<Player>();

4.2. 親オブジェクトのスクリプトにアクセス

Player playerScript = GetComponentInParent<Player>();

5. FindObjectOfType を使う

どんなときに使う?

  • シーン内に 1つだけ特定のスクリプトがある場合
  • デバッグ用に サクッと取得したいとき

コード

Player playerScript = FindObjectOfType<Player>();
if (playerScript != null)
{
    playerScript.TakeDamage(10);
}

注意点

⚠️ シーン内に 複数のPlayerスクリプトがあると意図しないオブジェクトが取得される
⚠️ シーン全体を検索するため、パフォーマンスが悪い


6. Singleton パターンを使う(高度な方法)

どんなときに使う?

  • プレイヤーなど シーン全体で1つだけ存在するオブジェクト にアクセスするとき。
  • どこからでも簡単にアクセスしたいとき

6.1. Singleton を作る

public class Player : MonoBehaviour
{
    public static Player Instance { get; private set; }

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void TakeDamage(int damage)
    {
        Debug.Log("プレイヤーの残りHP: " + health);
    }
}

6.2. Singleton を使う

if (Player.Instance != null)
{
    Player.Instance.TakeDamage(10);
}

メリット

どこからでも簡単にアクセス可能!
毎回検索する必要なし

デメリット

⚠️ シングルトンの設計を間違えるとバグの原因になる


まとめ

方法使いどころ
Findシーン内に1つだけのオブジェクト
FindWithTag名前が変わってもOK
SerializeField最もおすすめ!
GetComponentInChildren親子関係あり
FindObjectOfTypeデバッグ用
Singletonどこからでもアクセス

→ ゲームの状況に合わせて最適な方法を選ぼう!

Unity

Posted by hidepon