皆さんはUnityでオブジェクトを自在に動かせていますか?例えばシューティングゲームの弾をイメージしてみてください!
まっすぐ飛ぶだけの弾、ゆっくり追尾してくる弾、軸を中心に周りながら飛んでくる弾…いろいろな動きをするオブジェクトが存在しますよね!
このような様々な動きを再現するには、オブジェクトの座標について詳しくなる必要があります。というわけで、今回はUnityの座標を保持している、transform.positionについてみていきたいと思います!
前半で、以下のような基本的な内容をまずは理解しましょう。
- transform.positionとは?
- transform.positionの変更方法
- ローカル座標・ワールド座標について
後半は、基礎的なオブジェクトの移動方法をまとめておきましたので、実際挙動を確かめながら動かしてみてください。きっとオブジェクトの挙動について理解が深まりますよ!
それでは一緒にみていきましょう。
transform.positionとは?
まずは、transformが何者なのか見てみましょう!
まずはtransformとは?
簡単に言ってしまうと、オブジェクトの位置と回転とサイズを保持しているクラスです。
早速公式のリファレンスを見てみましょう。
オブジェクトの位置、回転、スケールを扱うクラス
シーン内のすべてのオブジェクトは Transform を持ちます。Transform はオブジェクトの位置、回転、スケールを格納し、操作するために使用されます。すべての Transform は親を持ち、階層的に位置、回転、スケールを適用することができます。これはヒエラルキーウインドウで階層を見ることができます。
参照元:https://docs.unity3d.com/ja/current/ScriptReference/Transform.html
「位置、回転、スケールを格納し、操作するために使用されます。 」という部分です。「transform」には位置、回転、スケールが保持されているんです。そう、今回の主役となるオブジェクトの位置が保持されているわけです!
またtransfromについてもっと詳しく知りたい方はこちらの記事を御覧ください。
transform.positionとは
「transform」にはオブジェクトの位置が保持されていることがわかりました。
ではどこに保持されているのでしょうか?答えは簡単です。今回の主役transform.positionです。このtransform.positionには、Vector3型で各座標が入っています。そして、x,y,z変数へ、XYZ座標がfloat型で入っています。
transform.position.x ・・・ X座標
transform.position.y ・・・ Y座標
transform.position.z ・・・ Z座標
※float型とは、例えば「0.001」のように小数点を含む数字を入れることができる型のことです。
必要な座標情報がある場合はここから取り出しましょう。
transform.position の変更方法
それでは、実際にtransform.positionをどう扱うのかに入っていきましょう。
下準備
その前に、まずは今回使用するオブジェクトを準備しましょう。何かオブジェクトを作成し、新たにスクリプトをAddComponentしましょう。
上の画像は、以下の流れで作った例です。
①Hierarchy上で「右クリック→3DObject→Cube」とCubeオブジェクトを作り選択し。
②「AddComponent ボタンをクリック→NewScript→MainCharacterという名前でCreateAndAdd」
スクリプトがついたオブジェクトの作り方がわからない人は参考にしてみてください。
このあとは、紐付いたスクリプトをダブルクリックなどすればプログラムを開くことができます。
transform.position の取得・変更方法
まずは簡単にソースを見てみましょう。
// オブジェクトに紐付いている関数 public class MainCharacter : MonoBehaviour { // 更新用の関数 void Update() { // transformを取得 Transform myTransform = this.transform; // 座標を取得 Vector3 pos = myTransform.position; pos.x += 0.01f; // x座標へ0.01加算 pos.y += 0.01f; // y座標へ0.01加算 pos.z += 0.01f; // z座標へ0.01加算 myTransform.position = pos; // 座標を設定 } }
これは、オブジェクトのxyzの各座標を、0.01ずつ加算し移動させているプログラムです。実行すると、ゆっくり斜め後ろ横方向にオブジェクトが移動するでしょう。
「Vector3 worldPos = myTransform.position;」の部分で、Vector3型で座標を取得しています。先ほども説明しましたが、Vector3には、x座標、y座標、z座標が入っています。それぞれ、pos.x、pos.y、pos.zといった変数に入っていますので、編集する場合や取得する場合これらの変数を利用することとなります。
今回は取得した座標データ(pos.x、pos.y 、pos.z)に0.01加算し、最後に「myTransform.position = pos」で変更後の座標をオブジェクトへ設定しているわけです。
手取り早くオブジェクトを移動したい場合は、このプログラムを参考にしてみてください。
「transformposition.x+= 0.01f;」じゃダメ?
プログラムに多少詳しい人なら、「transform.position.x+= 0.01f;」と、直接加算してはダメなのか?といった感想が出てくると思います。
しかし直接の代入ではエラーが出てしまうのです。position変数のアクセス修飾子の設定により、直接変更はできないことが理由です。そのため変更するときは「myTransform.position = pos」のようなアクセサーを使用する方法で値を編集しましょう。
※アクセス修飾子やアクセサーがわからない人も、直接はアクセスできないのだと覚えておいてもらえれば構いません。
ローカル座標・ワールド座標について
座標の操作を行う上で、難しい点の一つとして、ローカル座標とワールド座標があります。二つの違いを、簡単に言ってしまえば以下のようになります。
ワールド座標とは、3D空間全体の中心を中心座標(x=0,y=0,z=0)として自分がどこにいるのかを表す座標。
ローカル座標とは、親のいる座標を中心座標(x=0,y=0,z=0)とした座標。
Unityでは、オブジェクト同士で親子関係を作ることができます。その際「親の座標」を中心とするかどうかがこの二つの座標系の違いです。親子関係についてはtransformが保持していますので、詳細は以下のリンクのtransformについてお読みください。
いろいろな座標操作方法
ここからはシンプルに、座標を取得する方法と、更新する方法を並べておきました。プログラムを組む上での参考にしてください。
ワールド座標変更方法
まずはワールド座標での座標操作を見てみましょう。ワールド座標を取得・変更するには、取得した「transform.position」を使用します。
基本的に初心者はワールド座標を扱うことが多いと思いますので、まずはワールド座標に関した操作を覚えましょう。
ワールド座標での座標取得方法
ワールド座標で、xyz座標を取得するプログラムです。
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // ワールド座標を基準に、座標を取得 Vector3 worldPos = myTransform.position; float x = worldPos.x; // ワールド座標を基準にした、x座標が入っている変数 float y = worldPos.y; // ワールド座標を基準にした、y座標が入っている変数 float z = worldPos.z; // ワールド座標を基準にした、z座標が入っている変数 } }
ワールド座標での座標移動
単純に先ほどの取得処理に、代入処理を追加したものです。
この処理を実行すると、オブジェクトの座標がx=1,y=1,z=1に移動されます。
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // ワールド座標を基準に、座標を取得 Vector3 worldPos = myTransform.position; worldPos.x = 1.0f; // ワールド座標を基準にした、x座標を1に変更 worldPos.y = 1.0f; // ワールド座標を基準にした、y座標を1に変更 worldPos.z = 1.0f; // ワールド座標を基準にした、z座標を1に変更 myTransform.position = worldPos; // ワールド座標での座標を設定 } }
ワールド座標での相対的な座標移動
Translate関数を利用すると、現在の位置から相対的に移動することができます。ただしワールド座標で相対的な移動をさせるには、第4引数に「Space.World」が引数に必要なのを忘れないようにしましょう。
この第4引数を省略した場合、ローカル座標で相対的な座標移動作となってしまいます。
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // 現在の座標からのxyz を1ずつ加算して移動 myTransform.Translate (1.0f, 1.0f, 1.0f, Space.World); } }
ローカル座標変更方法
次にローカル座標での座標操作を見てみましょう。ローカル座標を取得・変更するには、取得した「transform.localPosition」を使用します。
親のオブジェクトを中心に移動させる場合に、ローカル座標を使用することになります。
ローカル座標での座標取得方法
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // ローカル座標を基準に、座標を取得 Vector3 localPos = myTransform.localPosition; float x = localPos.x; // ローカル座標を基準にした、x座標が入っている変数 float y = localPos.y; // ローカル座標を基準にした、y座標が入っている変数 float z = localPos.z; // ローカル座標を基準にした、z座標が入っている変数 } }
ローカル座標での座標移動
ワールド座標の時と同じですね。
localPositionで取得した座標に、代入を行い、再度localPositionへ代入しています。
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // ローカル座標での座標を取得 Vector3 localPos = myTransform.localPosition; localPos.x = 1.0f; // ローカル座標を基準にした、x座標を1に変更 localPos.y = 1.0f; // ローカル座標を基準にした、y座標を1に変更 localPos.z = 1.0f; // ローカル座標を基準にした、z座標を1に変更 myTransform.localPosition = localPos; // ローカル座標での座標を設定 } }
ローカル座標での相対的な座標移動
Translate関数を利用すると、現在の位置から相対的に移動することができます。
public class MainCharacter : MonoBehaviour { void Update() { // transformを取得 Transform myTransform = this.transform; // 現在の座標からのxyz を1ずつ加算して移動 myTransform.Translate (1.0f, 1.0f, 1.0f); } }
まとめ
いかがでしたでしょうか?
今回は必要最低限の、移動処理を説明しました。この処理さえ覚えておけば、オブジェクトの基本的な移動は行えます。
ただし、オブジェクトに様々な動きをさせたり、物理演算処理を行いたい場合は、まだまだ他の知識も必要になってきます。引き続き移動処理を極めていきましょう。