【Unity】他のスクリプトの関数を呼び出す・変数を取得

当サイトで紹介する商品・サービス等の外部リンクは、アフィリエイト広告を含む場合があります。
スポンサーリンク

小規模なゲーム(個人制作の同人ゲーム)でも数千行以上のスクリプトを書く必要があり、誰でも知っているようなタイトルではそれ以上のスクリプトが必要となり数万行は超えてきます。

Unityだけではなく、1つのスクリプトで1万行もコードを書くと見づらくなりかえって複雑になってしまいます。そこで、複数のスクリプトを用意し関数を呼び出してゲームを完成させます。

例えば、RPGにてキャラクターを移動させるときの関数。敵を倒してスコアを加算する時の関数。セーブする関数などこれらを別のスクリプトの関数として必要な時にだけ呼び出します。

このように2つ以上のスクリプトをつくって他のスクリプトで定義した変数や関数を呼び起こす場面は開発中に何度もあります。

また、別のスクリプトから変数をアクセス(使う)場合はstatic(静的)にする必要がありますが、static変数はゲームを終了して再開しても値を保持できないことやクラス間の依存関係の増加など致命的な問題があります。

したがって、本記事ではstaticを使わずに、別スクリプトの関数を呼び起こす方法を紹介します。

本記事は次の人におすすめ
  • 他のスクリプトの関数を呼び出したい。
  • 他のスクリプトの変数を取得したい。
  • static以外で変数にアクセスしたい。
  • 「GetComponent<>();」の使い方を知りたい。
スポンサーリンク

参照先のスクリプトを取得する方法

参照先のスクリプトを取得するには「同じGameObjectにアタッチされている」、あるいは「別のGameObjectアタッチされている」2つの場合でコード記述が異なります。

GameObjectとは、名前の通りゲームの物体を意味しHierarchyウィンドウで追加や削除など扱います。通常スクリプトはこのGameオブジェクトにアタッチして実行させます。

アタッチする方法は、Inspectorウィンドウの最下部「Add Component」から追加、あるいはドラッグ&ドロップで追加する方法があります。

一方でGetComponentは、Unityでゲームオブジェクトにアタッチされたコンポーネントを取得するためのメソッドです。取得には、次の通りに書きます。

GetComponent<コンポーネントの型>()

同じGameObjectにアタッチされている場合

初めに、同じGameObjectにアタッチされている別スクリプト(SampleA.csとSampleB.cs)のコード例を紹介します。

左クリックすると、iが加算されるコードです。
SampleA.csがSampleB.csを参照します。

  • SampleA.cs (呼び出す側)
SampleB plus;

    void Start()
    {
        plus = GetComponent<SampleB>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // マウスの左ボタンが押された場合
        {
      plus.Increment();
      Debug.Log(plus.i);
        }
    }
  • SampleB.cs (呼び出される側)
public int i = 0;

public void Increment(){
 i++;
}

他のスクリプトから呼び出す関数と変数は、publicにしておきます。

異なるGameObjectにアタッチされている場合

アタッチするGameObjectはどれにしても同じというわけではないです。

例えば、敵キャラを倒すと加算されるスコアが異なる。HPが違うというようにステータスを変える場合は、それぞれの敵オブジェクトにスクリプトをアタッチしなければいけません。

SampleB plus;

    void Start()
    {
        // "Enemy"という名前のGameObjectにアタッチされていると仮定
        GameObject obj = GameObject.Find("Enemy");
        plus = obj.GetComponent<SampleB>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // マウスの左ボタンが押された場合
        {
      plus.Increment();
      Debug.Log(plus.i);
        }
    }

同じGameobjectと異なることは、「GameObject.Find(“オブジェクト名”)」を記述してGameObjectを探してGetComponentします。

番外:インスペクターで紐づけ

GetComponentを使わないInspectorで紐づけもできます。これは「関数も変数もpublic」にしてオープン状態にしておきます。

  • SampleA.cs (呼び出す側)
public SampleB plus;

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // マウスの左ボタンが押された場合
        {
      plus.Increment();
      Debug.Log(plus.i);
        }
    }
  • SampleB.cs (呼び出される側)
public int i =0;

public void Increment(){
 i++;
}

GetCompornentを使わずに他のスクリプトを呼び出すことができますが、必ずInspectorでセットする必要があります。未設定だとNullReferenceExceptionが出てきてしまいます。

GetComponentで別スクリプトの関数を呼び起こす方法

それでは、別のスクリプトから関数を呼び出す方法を解説します。

今回はスクリプト「ScriptA.cs」「ScriptB.cs」の2つを使います。

「ScriptB.cs」にて、スペースキーを押すと、「ScriptA.cs」の関数で変数を加算するコードです。

関連記事:「【Unity】UIボタンを押すごとに数字を増やし、クリックした回数をカウントをする」

ソースコード

関数を渡す側

using UnityEngine;

public class ScriptA : MonoBehaviour
{
    int Count;
    public void MethodA()
    {
        Count++;
        Debug.Log(Count);
    }
}

関数を受け取る側

using UnityEngine;

public class ScriptB : MonoBehaviour
{
    private ScriptA scriptA;

    private void Start()
    {
        scriptA = GetComponent<ScriptA>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
       Debug.Log("Spaceキーが入力されました");
            scriptA.MethodA();
        }
    }
}

解説

初めに、「ScriptA」を解説します。

「Count」はint型変数で、関数「MethodA()」内で「Count」を1ずつ加算します。

    int Count;
    public void MethodA()
    {
        Count++;
        Debug.Log(Count);
    }

つづいて、「ScriptB」を解説します。

scriptAは、クラス「ScriptA」のprivateなインスタンス変数です。

同じGameObjectにアタッチされているScriptAを探して、変数「scriptA」に格納します。GetComponentは新しく作るのではなく、すでにあるものを探して返します。
よって、別のスクリプト(ScriptB)からScriptAクラスで定義されたメンバー変数、メソッド、プロパティにアクセスすることができます。

  private ScriptA scriptA;

また、Start()内で、privateな変数「scriptA」にGetComponentメソッドを使用して、スクリプトで定義されたメソッドや変数にアクセスします。

 scriptA = GetComponent<ScriptA>();

最後にUpdate()内で、スペースキーを押すと、スクリプト「ScriptA」内の関数MethodA()を実行させます。

if (Input.GetKeyDown(KeyCode.Space))
{
 Debug.Log("Spaceキーが入力されました");
scriptA.MethodA();
}

実演

完成した2つのスクリプトをHierarchyウィンドウにアタッチしてください。

再生ボタンを押して、スペースキーを押すと以下のようになります。

なお、Unity 6.1以降の新規プロジェクトでは、入力の設定が新しいInput Systemになっています。この記事のInput.GetKeyDownやInput.GetMouseButtonDownは従来のInput Managerの書き方なので、そのままだと「InvalidOperationException」のエラーが出ます。

その場合は、メニューのEdit > Project Settings > Playerで、Active Input Handlingを「Both」にしてください。公式ドキュメントでも、新規プロジェクトではInput Systemパッケージの利用が推奨されています。

他のスクリプトの変数を取得する

関数だけでなく、変数も同じ流れで取得できます。GetComponentで参照を取ったあとに「scriptA.Count」のように書けば、ScriptAの変数を読めます。

ただし、他のスクリプトから読める変数はpublicにする必要があります。値を書き換えられたくないときは、読むだけ許可してセット(書き込み)はScriptAの中だけにします。

// ScriptA.cs
public class ScriptA : MonoBehaviour
{
    public int Count { get; private set; }

    public void MethodA()
    {
        Count++;
    }
}
// ScriptB.cs
private ScriptA scriptA;

private void Start()
{
    if (TryGetComponent(out scriptA))
    {
        Debug.Log(scriptA.Count);
    }
    else
    {
        Debug.LogWarning("ScriptAがアタッチされていません");
    }
}

TryGetComponentは、取得できたかどうかをtrueかfalseで返します。アタッチを忘れたときにNullReferenceExceptionにならず、原因を見つけやすくなります。

まとめ

今回は、staticを使わず、別スクリプトの関数を呼び起こす方法を紹介しました。

関数を呼び起こすためには、「GetComponent()」を使い、呼び起こしたい関数があるクラスを探して、privateな変数に入れます。

privateな変数を用意することで、そのスクリプト内のみで変数が有効になるので、別のスクリプトからの干渉を受ける心配はなくなります。

タイトルとURLをコピーしました