WisdomSoft - for your serial experiences.

移動

ゲーム中にオブジェクトを動かすには、オブジェクトの座標をスクリプトから制御します。

指定座標にオブジェクトを配置する

Unity エディタからオブジェクトに対して行える設定は、スクリプトからも同様に設定できます。Unity ではオブジェクトが持つ状態はすべてコンポーネントと呼ばれる個別の部品の組み合わせで構成されています。オブジェクトが持つコンポーネントは「Inspector」ウィンドウに表示されています。

図1 オブジェクトが持つコンポーネントの一覧
オブジェクトが持つコンポーネントの一覧

通常、コンポーネントは Unity ユーザーインタフェース上のメニューにある「Component」メニューから追加できますが、必要であればスクリプトからコンポーネントの追加や削除を行うこともできます。Unity は標準で多くのコンポーネントを提供していますが、それらはすべて UnityEngine.Component クラスから派生しています。

UnityEngine.Component クラス
UnityEngine.Object
    UnityEngine.Component
public class Component : Object

興味深いことに Unity のスクリプト自身もまた Component クラスを継承する MonoBehaviour クラスを実装するため、コンポーネントの一種として管理されます。

オブジェクトに設定されているスクリプト(MonoBehaviour)自身の transform プロパティを変更することで、スクリプトが設定されているオブジェクトの位置を変更できます。

Component クラス transform プロパティ
public Transform transform { get; }

このプロパティは、オブジェクトの座標や向き、大きさを表す UnityEngni.Transform クラスを返します。このクラスのオブジェクトは「Inspector」ウィンドウに表示されている Transform に相当する機能を提供します。

UnityEngni.Transform クラス
UnityEngine.Object
    UnityEngine.Component
    	UnityEngine.Transform
public class Transform : Component, IEnumerable

オブジェクトの空間内における位置を変更するには position プロパティを変更します。同様に、このプロパティからオブジェクトの現在位置を取得できます。

Transform クラス position プロパティ
public class Vector3 position { get; set; }

このプロパティは、オブジェクトの座標を表す原点からのベクトルを Vector3 構造体で表します。

コード1
using UnityEngine;

public class Test : MonoBehaviour 
{
	void Start ()
	{
		transform.position = Vector3.zero;
	}
}
コード1 実行結果
コード1 実行結果 コード1 実行結果

コード1は実行するとオブジェクトの座標を原点 (0, 0, 0) に移動させるスクリプトです。自分自身の transform プロパティが返す Transform オブジェクトの position プロパティに Vector3.zero を代入しています。このときの position プロパティに設定する Vector3 構造体の値が、新しいオブジェクトの座標となります。

実行結果の最初の画像は実行前のオブジェクトの状態、2 番目の画像が実行中の状態です。Inspector の Position を見ると、正しく座標が変更されていることが確認できます。

ワールド座標系とローカル座標系

Unity のシーンに登録されているオブジェクトは親子関係でグループ化されます。現在のシーンでインスタンス化されているオブジェクトの構造は「Hierarchy」ウィンドウで確認できます。

図2 親子関係を持つオブジェクト
親子関係を持つオブジェクト

このとき、オブジェクトの位置や向き、サイズといった変換情報は親オブジェクトの影響をうけます。Unity エディタ上で親オブジェクトを移動させれば、関連付けられているすべての子オブジェクトも親に合わせて移動します。つまり、親オブジェクトに対して子オブジェクトは相対的に作用します。

親オブジェクトとは無関係に、空間の原点を中心にした座標系をワールド座標と呼び、これに対して親オブジェクトの座標を原点とした座標系をローカル座標と呼びます。

通常、スクリプトからオブジェクトを操作するときはローカル座標を想定するでしょう。ところが、前述した position プロパティはワールド座標を表すため、親オブジェクトとは無関係に空間全体の原点を軸としています。そうではなく、親オブジェクトを中心としたローカル座標で移動させたい場合は localPosition プロパティを使ってください。

Transform クラス localPosition プロパティ
public Vector3 localPosition { get; set; }

position プロパティとの違いは、このプロパティで読み書きする値はオブジェクトのローカル座標、すなわち親オブジェクトの原点を軸にしていることです。よって、スクリプトから座標を変更しても、親との関係が無視されることはなくなります。

コード2
using UnityEngine;

public class Test : MonoBehaviour 
{
	void Start () 
	{
		transform.localPosition = Vector3.zero;
	}
}
コード2 実行結果
コード2 実行結果1 コード2 実行結果2

コード2は localPosition プロパティにゼロのベクトルを設定しているため、ローカル座標系の原点にオブジェクトを移動させます。実行結果の例では 2 つの立方体を共通の Owner 親オブジェクトに追加し、それぞれ親の原点から X 軸方向に距離を取った状態で開始しています。最初の画像が実行前、2番目の画像が実行中の状態です。

Owner オブジェクトはワールド座標の原点に対し Z 軸が -3 の位置まで移動させています。親オブジェクトの位置に合わせて、子オブジェクトである立方体も同様に Z 軸が -3 の位置に移動しています。

スクリプトは画面から向かって右側の立方体にのみ設定して開始しています。実行結果から、立方体の位置が親の原点まで移動することが確認できます。

localPosition プロパティではなく、ワールド座標系の position プロパティを用いれば、ローカル座標系とワールド座標系の違いを体験できるでしょう。

図3 コード2をワールド座標で実行した場合
親子関係を持つオブジェクト

図3コード2のスクリプトを書き換え、position プロパティに対してゼロのベクトルを設定したものです。この場合、立方体は親の原点ではなくワールド座標(世界全体)の原点に移動してしまいます。ワールド座標系では、親の座標は作用しません。

移動

position プロパティや localPosition プロパティを用いることで、オブジェクトの位置を自由に変更できます。ゲーム中では、オブジェクトの現在の位置から指定した距離を移動させるという処理が多くなりますが、移動処理には Translate() メソッドを使うこともできます。このメソッドはオーバーロードされています。

Transform クラス Translate() メソッド
public void Translate(float x, float y, float z)
public void Translate(Vector3 translation)

X 軸の移動量は x パラメータ、Y 軸の移動量は y パラメータ、Z 軸の移動量は z パラメータに、それぞれ指定します。

translation パラメータには、移動量を表す Vector3 型のベクトルを指定します。

このメソッドは、オブジェクトの現在の位置から指定したベクトルだけ移動します。同様の処理は position プロパティや localPosition プロパティに対して複合代入演算で値を加えても可能です。

transform.position += new Vector3(x, y, z);

Translate() メソッドによるオブジェクトの移動は、上記のコードと同義です。

コード3
using UnityEngine;

public class Test : MonoBehaviour 
{
	void Start () 
	{
		transform.Translate(2, 0, 0);
		transform.Translate(0, 1, 0);
		transform.Translate(0, 0, -3);
	}
}
コード3 実行結果
コード3 実行結果

コード3は Translate() メソッドを複数呼び出して、オブジェクトを移動させています。このプログラムで Translate() メソッドの呼び出しを分割する意味はありませんが、このメソッドによる移動が現在位置からのベクトルの加算であることを確認するために、このような処理にしています。

Translate() メソッドは、キー入力や時間によって指定の方向に一定の量で移動させるような処理に適しているでしょう。