Unity エディターからインスペクタ上のコンポーネントのプロパティを変更できます。例えば,トランスフォーム コンポーネントの位置の値への変更はゲームオブジェクトの位置に反映されます。同様にレンダラのマテリアルの色を変更したり,リジッドボディの重さを変更してゲームオブジェクトの動きを変えられます。スクリプティングの多くはゲームオブジェクトを操作するためにコンポーネントのプロパティを修正します。違いがあるのは,スクリプトは時間の経過とともにプロパティの値を徐々に増やしたり,ユーザ入力への反応として変更させることが出来るところです。適切なタイミングでオブジェクト作成や破棄を行なうことでゲームプレイの実装が出来ます。
スクリプトが同じゲームオブジェクトにある他のコンポーネントへのアクセスが必要な場合がありますが,これが最も単純でよくあるケースです。イントロダクションなどで既に述べているとおり,コンポーネントはクラスのインスタンスであるため,コンポーネント インスタンスへの参照をまずは取得します。これには GetComponent 関数を使います。通常,コンポーネント オブジェクトを何らかの変数に割り当てたいため C# の場合は次の構文を使います:
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
}
UnityScript では構文がわずかに異なります:
function Start () {
var rb = GetComponent.<Rigidbody>();
}
コンポーネント インスタンスへの参照が取得できた後は,インスペクタ上でセットするのと同様にプロパティの値をセットできます:
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
// Change the mass of the object's Rigidbody.
rb.mass = 10f;
}
インスペクタ上では利用できない機能はコンポーネント インスタンスの関数を呼ぶパターンです:
void Start () {
Rigidbody rb = GetComponent<Rigidbody>();
// Add a force to the Rigidbody.
rb.AddForce(Vector3.up * 10f);
}
同じオブジェクトに一つ以上のカスタムのスクリプトをアタッチできることに注意して下さい。もし一つのスクリプトから別のものへアクセスが必要である場合,通常どおり GetComponent 関数を使用したうえでコンポーネントの型を指定するためにスクリプト クラス名(あるいはファイル名)を使用します。
もしゲームオブジェクトに追加されてないコンポーネントを取得しようと試みた場合,GetComponent は null を返します。実行時に null オブジェクトの値を変更しようとすると,null 参照エラーとなります。
いくつかのコンポーネント型は良く使われるため, Unity はビルトイン変数により MonoBehaviour クラスでアクセスできるため,次のような使い方が出来ます:
void Start () {
transform.position = Vector3.zero;
}
これは GetComponent を使用せずトランスフォーム コンポーネントにアクセス出来ています。ビルトイン コンポーネント変数の一覧は MonoBehaviour スクリプト リファレンスを参照して下さい。GetComponent と同様に,指定したコンポーネントがゲームオブジェクトに追加されてない場合,変数は null となります。
オブジェクトが独立して動作するとはいえ,スクリプトが他のオブジェクトを管理することが良くあります。例えば,追いかけてくる敵がプレイヤーの位置を知る必要があるとしましょう。Unity でオブジェクトを取得する方法は複数あり,状況に応じて使い分けます。
ゲームオブジェクトを見つける最も分かりやすい方法は public であるゲームオブジェクト変数をスクリプトに追加することです:-
public class Enemy : MonoBehaviour {
public GameObject player;
// Other variables and functions...
}
この変数は他と同様にインスペクタ上で表示されます:
シーンまたは階層パネルからオブジェクトをこの変数の上にドラッグして割り当てることが出来ます。このオブジェクトは他と同様に GetComponent 関数およびコンポーネントにアクセスできる変数が利用可能となります。そのため,次のようなコードが使用できます:
public class Enemy : MonoBehaviour {
public GameObject player;
void Start() {
// Start the enemy ten units behind the player character.
transform.position = player.transform.position - Vector3.forward * 10f;
}
}
さらに,もしスクリプトの中でコンポーネント型の public である変数を宣言すると,コンポーネントがアタッチされている任意のゲームオブジェクトをその上にドラッグできます。これはゲームオブジェクト自身ではなくコンポーネントを直接アクセスします。
public Transform playerTransform;
変数にオブジェクトをリンクさせることは永続的にそのオブジェクトを使い続ける上で最も実用的な方法です。同じタイプのオブジェクトを配列で保持することが出来ますが,それはランタイムで行うよりもむしろUnityエディター上で行う必要があります。これは多くの場合,ランタイムでオブジェクトの位置を突き止めるのに便利であり,これを行う方法として2つの方法を提供しています。
ゲーム シーンにおいて同じ型のオブジェクトを複数使用する場合があり,敵,巡回点,障害物などに使われます。この場合に別のスクリプトによりそれらへの反応をまとめて管理することが必要となるかもしれません(例.全ての巡回地点を経路探索のスクリプトで利用可能とする)。変数を使用してこれらのオブジェクトを紐付けるのは一つの方法ですが,新しい巡回地点をスクリプト上の変数にドラッグするのは設計上も面倒です。同様に,もし巡回点を削除したときに削除オブジェクトだけ変数の参照を取り除くのも面倒でしょう。このような場合,一つの親オブジェクトの子オブジェクトとすることで,全てを管理するのが良い解決策です。子オブジェクトは親オブジェクトのトランスフォーム コンポーネントを通して取得できます(全てのオブジェクトには明示的にトランスフォームがあるため):
public class WaypointManager : MonoBehaviour {
public Transform waypoints;
void Start() {
waypoints = new Transform[transform.childCount];
int i = 0;
for (Transform t in transform) {
waypoints[i++] = t;
}
}
}
名前を指定して特定の子オブジェクトを見つけるには Transform.Find 関数を使用します:
transform.Find("Gun");
これはオブジェクトがゲームの途中で追加,削除する子オブジェクトがある場合に便利です。拾ったり捨てたりできる武器が分かりやすい例です。
識別できる情報があるかぎり,シーン階層上のどこでもゲームオブジェクトを見つけることが出来ます。名前を指定して個別オブジェクトを取得するには GameObject.Find 関数を使用します:
GameObject player;
void Start() {
player = GameObject.Find("MainHeroCharacter");
}
オブジェクトまたはその集合をタグを使用して見つけるには GameObject.FindWithTag , GameObject.FindGameObjectsWithTag 関数を使用します:
GameObject player;
GameObject[] enemies;
void Start() {
player = GameObject.FindWithTag("Player");
enemies = GameObject.FindGameObjectsWithTag("Enemy");
}