Unity エディターでは、インスペクターを使用してコンポーネントプロパティーを変更します。例えば、Transform コンポーネントの Position の値を変更すると、ゲームオブジェクトの位置を変更できます。同様に、ゲームオブジェクトの外観や挙動に対応して、レンダラーのマテリアルの色やリジッドボディの質量を変更できます。スクリプトを使った方法でも、コンポーネントプロパティーを変更してゲームオブジェクトを操作するということはほとんど同じです。さらに、スクリプトを使うと、時間の経過と共にプロパティーの値を徐々に変えたり、または、ユーザーからの入力に応じてプロパティーの値を変えることができます。適切なタイミングでオブジェクトを変更、作成、破棄することで、あらゆる種類のゲームを実装できます。
同じゲームオブジェクトにある、他のコンポーネントへのアクセスを必要とする場合がよくあります。イントロダクションなどですでに述べている通り、コンポーネントはクラスのインスタンスであるため、まずはコンポーネントインスタンスの参照を取得します。これには GetComponent 関数を使います。通常、コンポーネントオブジェクトをなんらかの変数に割り当てたい場合 C#で は次の構文を使います。
void Start ()
{
Rigidbody rb = GetComponent<Rigidbody>();
}
コンポーネントインスタンスへの参照が取得できた後は、インスペクター上で行うのと同様にプロパティーの値を設定できます。
void Start ()
{
Rigidbody rb = GetComponent<Rigidbody>();
// オブジェクトのリジッドボディの質量を変更します。
rb.mass = 10f;
}
インスペクター上では利用できないことはコンポーネントのインスタンス化を行う関数を呼ぶことです。
void Start ()
{
Rigidbody rb = GetComponent<Rigidbody>();
// リジッドボディに力を加えます。
rb.AddForce(Vector3.up * 10f);
}
同じオブジェクトに 1 つ以上のカスタムのスクリプトをアタッチできることに注意してください。もしあるスクリプトから別のものへアクセスが必要である場合、通常どおり GetComponent 関数を使用したうえでコンポーネントの型を指定するためにクラス名(あるいはファイル名)を使用します。
もしゲームオブジェクトに加えられていないコンポーネントを取得しようとすると、GetComponent は null を返します。ランタイムに null オブジェクトの値を変更しようとすると、null 参照エラーとなります。
スクリプトは個別に操作を行うこともありますが、他のオブジェクトも一緒に管理することが一般的です。例えば、追いかけてくる敵はプレイヤーの位置を知る必要があるように。Unity で他のオブジェクトを取得する方法は複数あり、状況に応じて使い分けてください。
関連するゲームオブジェクトを見つけるもっとも簡単な方法は public であるゲームオブジェクト変数をスクリプトに加えることです。
public class Enemy : MonoBehaviour
{
public GameObject player;
// その他の変数と関数...
}
この変数は他と同様にインスペクター上に表示されます。
シーンまたは Hierarchy ウインドウからオブジェクトをこの変数の上にドラッグして割り当てることができます。このオブジェクトは他と同様に GetComponent 関数およびコンポーネントにアクセスできる変数を利用できます。そのため、以下のようなコードを使用できます。
public class Enemy : MonoBehaviour {
public GameObject player;
void Start() {
// プレイヤーキャラクターから 10 ユニット遅れてエネミーを開始
transform.position = player.transform.position - Vector3.forward * 10f;
}
}
さらに、もしスクリプトの中でコンポーネント型の public である変数を宣言すると、コンポーネントがアタッチされている任意のゲームオブジェクトをその上にドラッグできます。これはゲームオブジェクト自身ではなくコンポーネントに直接アクセスします。
public Transform playerTransform;
変数でオブジェクトをリンクさせることは、永続的に関連するオブジェクトを処理するときにとても便利です。配列の変数を使って同じ型のオブジェクトを関連付けることができます。しかし、関連付けはランタイムで行うよりも Unity エディター上で行う必要があります。ランタイムにオブジェクトを配置するのが便利な場合がしばしばあります。これを行う方法として Unity では、以下の 2 つの方法があります。
ゲームのシーンでは、敵、ウェイポイント、障害物など、同じ種類の多くのゲームオブジェクトを使用することがしばしばあります。これらのオブジェクトは、監視または反応する特定のスクリプトによって追跡されることがあります (例えば、すべてのウェイポイントは、経路探索スクリプトで使用可能です)。変数を使用してこれらのゲームオブジェクトを関連付けることは可能ですが、新しいウェイポイントを 1 つずつスクリプト上の変数にドラッグする必要がある場合、設計面での処理が面倒になります。同様に、ウェイポイントを削除する場合に、欠けているゲームオブジェクトへの変数の参照を削除する必要があります。このような場合、ゲームオブジェクトの群をすべて 1 つの親ゲームオブジェクトの子にすることによって管理するほうが良いことがあります。子のゲームオブジェクトは親の Transform コンポーネントを使用して取得できます (なぜなら、すべてのゲームオブジェクトに暗黙的に Transform があるからです)。
using UnityEngine;
public class WaypointManager : MonoBehaviour {
public Transform[] waypoints;
void Start()
{
waypoints = new Transform[transform.childCount];
int i = 0;
foreach (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");
}