[Unity]他のスクリプトを参照する

スクリプトから、他のスクリプトを参照したくなることがよくあります。今回はそのような場合にどのように参照するかを簡単に説明します。

他のスクリプトを参照する

スクリプトとは

そもそも制御用のスクリプトはどのような位置づけなのか。とても簡単で、「MonoBehaviour」を継承したクラスであるということです。詳しくは以下のページを参照してください。

[Unity]スクリプティングを始めるにあたって-継承-

上記のページの解説にあるとおり、MonoBehaviourはComponentクラスを継承した、コンポーネントであり、MonoBehaviourを継承した自作クラスもまたコンポーネントであるということです。つまり、オブジェクトに付加された指定したコンポーネント(スクリプト)を取得すれば自在にスクリプトを参照できるというわけです。

コンポーネントの取得方法

コンポーネントを取得するためには、Componentクラスに所属する「GetComponent」メソッドを利用します。何度も言いますが、MonoBehaviourクラスはComponentクラスを継承しています。その上でGetComponentメソッドは継承先でも利用できるクラスとなっているため利用できます。

http://docs.unity3d.com/Documentation/ScriptReference/Component.GetComponent.html


http://docs.unity3d.com/Documentation/ScriptReference/Component.GetComponent.html

使用例

GetComponentメソッドを利用した例を示します。今回の例に準備したシーンは以下のとおりです。

  • Sphere(球オブジェクト)
    • A(C# Script)
    • B(C# Script)
  • Main Camera
  • Directional Light

Sphereに付加した2つのスクリプトAとBは以下のとおりです。

using UnityEngine;
using System.Collections;

public class A : MonoBehaviour {
	public void PopUp(){
		gameObject.transform.Translate(0.0f,1.0f,0.0f);
	}
}
using UnityEngine;
using System.Collections;

public class B : MonoBehaviour {
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)){
			// マウスがクリックされたら以下を実行
			A a = GetComponent<A>();
			a.PopUp();
		}
	}
}

AクラスはPopUpメソッドが呼び出されると、オブジェクトの位置を上方へ1.0移動させます。

Bクラスはマウスがクリックされたら、GetComponentメソッドを利用して、コンポーネント(Aクラス)を取得します。取得したコンポーネントを利用してPopUpメソッドを実行します。この関係を図にすると以下のようになります。

translateSphere

実行結果

シーンとスクリプトを用意して実行すると、以下のようになります。

popup

実行し、クリックの都度に上方へ1づつ移動します。

解説

GetComponentメソッドはオブジェクトの付加されたコンポーネントを取得するメソッドです。

クラス 変数 = GetComponent<クラス名>();

このように、メソッド名の後に< >の間に取得したいクラスを指定し、取得したコンポーネントを保持するために、同じクラスの変数を用意し、代入します。ただし、キャストを利用すれば同じクラスである必要はありません。その点は理解でき人だけ利用すれば結構です。

今回のこの例では、同一のオブジェクトに2つのスクリプトを適用しました。ですので、GetComoponentメソッドは自身のコンポーネントを検索するために利用されました。もしAクラスを球オブジェクトに付加しないと以下の様なエラーが発生します。

bclassonly
getcomponenterror

このエラーは厳密にはAがないことよって引き起こされたエラーではありません。

			A a = GetComponent<A>();
			a.PopUp();

このコードの変数aには9行目では検索でAクラスが取得できなかったため「null」が格納されています。その「null」に対してPopUpメソッドを実行しようとしますが、「null」には当然そのようなメソッドがないためエラーが発生してしまいます。そのため、「null」かどうか監視することによってこのようなエラーを防ぐことができます。スクリプトを以下のように変更しました。

	void Update () {
		if(Input.GetMouseButtonDown(0)){
			A a = GetComponent<A>();
			if(a!=null){
				a.PopUp();
			} else {
				Debug.LogWarning("set Script A!");
			}
		}
	}

このように、aに対し「null」が格納されていたら、ログの警告を使うようにしました。これを実行してみると以下のように表示されます。

getcomponrntwarring

このようにしておけば、コンポーネントのつけ忘れでも警告をだして、知らせてくれます。(本当はtry-catchを使った方が良いのかもしれません。いずれまた。)

このプログラムでもう一つ重要なのが、

    public void PopUp(){

この「public」です。このpublicはInspectorに表示するためにも利用しましたが

[Unity]メンバ変数とインスペクタ

この「public」は外部(他のクラスから)「自由に読み書きしてよいですよ」というお墨付きです。「public」を付かなければ自動的に「private」扱いとなって、外部から読み書きはできなくなります。今回は外部のクラスBからAのPopUpメソッドを呼び出すわけですから、必ず「public」にしなければなりません。もし、「public」にしなければ、実行することすらできません。

accesslevelerror

このようにアクセスすることが許されません。

他のオブジェクトのスクリプトを参照する

他のオブジェクトのスクリプトを参照する場合も、自身のスクリプトを参照する場合と同じです。この場合、オブジェクトのコンポーネントと明確に指示しなければなりません。

使用例

GetComponentメソッドを利用した例を示します。今回の例に準備したシーンは以下のとおりです。

  • Sphere(球オブジェクト)
    • B(C# Script)
  • Cube(立方体オブジェクト)
    • A(C# Script)
  • Main Camera
  • Directional Light

このシーンは前述したシーンに対して、立方体オブジェクトを追加し、立方体オブジェクトに対してスクリプトAを付加し、球オブジェクトにはスクリプトBだけを付加しました。ただし、スクリプトBは外部のオブジェクトを参照できるように手を加えます。

using UnityEngine;
using System.Collections;

public class B : MonoBehaviour {
	public GameObject refObj;
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButtonDown(0)){
			A a = refObj.GetComponent<A>();
			if(a!=null){
				a.PopUp();
			} else {
				Debug.LogWarning("set Script A!");
			}
		}
	}
}

スクリプトA.csは前述から変更していませんので割愛します。

Sphereをアクティブにすると、InspectorウインドウのスクリプトBのエリアにGameObjectを指定することができるようになります。この領域に「Cube」オブジェクトをドラッグアンドドロップし、スクリプトのrefObjにCubeオブジェクトを割り当てます。

refobj

結果

実行し、画面上をクリックすると、スクリプトAが付加されたオブジェクトが上方へ移動します。

popupCube

解説

今回は前述した自身のスクリプトを取得する方法から少し変更され、他のオブジェクトに付加されたスクリプトを参照するようになりました。動きは前回と同じ、クリックをすると、スクリプトAが付加されたオブジェクトが上方へ移動します。これはスクリプトAのPopUpメソッドが実行されるためです。この関係を図にすると以下のようになります。

translateCube

今回はスクリプトBにフィールド(変数)としてGameObjectを「public」で指定し、Inspectorからゲームオブジェクトを指定できるようにしました。

refobj

これにより、スクリプトを実行した段階で自動的にフィールド(変数)refObjには「Cube」オブジェクトが代入されます。あとは

			A a = refObj.GetComponent<A>();

このように、そのオブジェクトのGetComponentメソッドを利用して、スクリプトを取得しました。

参照したいオブジェクトさえ手に入れれば、付加されたのコンポーネントを取得することは容易で、特別に難しいわけではありません。

おわりに

今回は、スクリプトから別のスクリプトを参照する方法を紹介しました。同一のオブジェクトでも、他のオブジェクトでもオブジェクト情報さえあれば、好きなコンポーネントを取得することが出来ます。今回の参照を利用すれば、例えば、点数を管理するオブジェクトとスクリプトを用意しておいて、敵が弾に当たる度に点数管理スクリプトに点数を加算すれば簡単に点数を管理することができます。色々試してみてください。

2014-12-26 コード中の < , > , ” が表示されていなかった問題を修正

[Unity]他のスクリプトを参照する” への4件のコメント

  1. 初心者にはわかりやすかったです。悩みが解決しました。

  2. C#スクリプト→javascript間のやりとりでも可能でしょうか?
    C#スクリプトで利用している変数をjavascript側に渡したいのですが・・・

コメントは受け付けていません。