脱初心者を目指すUnityブログ。
インスペクターのTransform を操作したり オブジェクトの親子関係を操作したりする Transformクラス について、メモを残しながら掘り下げていきたいと思います。
参考 : 公式リファレンス
Transform の注意点
【Unityの基本】Transformを徹底解説「移動」や「回転」だけじゃない
こちらで勉強させて頂きました。一部メモ。
・Transform は特別に、GetComponent が不要。(使うと無駄な負荷が増えるだけ)
・FixedUpdate で動かしてはいけない。
・Transform.Find は重いので基本的に避けた方が良い。
Transform のよく使う変数
位置情報
Transform.position
ワールド座標におけるオブジェクトの位置情報を、Vector3で格納する変数です。
private void Update() { //毎秒1mずつ上へ移動する transform.position += new Vector3(0, 1, 0) * Time.deltaTime; }
Transform .localPosition
Transform.position のローカル座標バージョンです。
private void Update() { //ローカル座標のY軸Positionが毎秒1ずつ増える //親から見た子のPositionなので、ワールド座標とは動きが異なる transform.localPosition += new Vector3(0, 1, 0) * Time.deltaTime; }
回転情報
Transform.up
ワールド座標で、Y軸上方向の単位ベクトルを取得できます。「上方向」を指したいときに使います。
同じくワールド座標「正面方向」は Transform.forward 、「右方向」は Transform.right 、それぞれ反対方向は符号を反転させて使います。
Rigidbody myRigidbody; float speed = 1.0f; private void Start() { myRigidbody = GetComponent<Rigidbody>(); } private void Update() { if (Input.GetKey(KeyCode.UpArrow)) { //velocity に上方向の単位ベクトル×speed を代入 myRigidbody.velocity = transform.up * speed; } if (Input.GetKey(KeyCode.DownArrow)) { //velocity に下方向の単位ベクトル×speed を代入 myRigidbody.velocity = -transform.up * speed; } }
Transform.rotation
ワールド座標におけるオブジェクトの回転情報を、Quaternion(四元数) で格納する変数です。
基本的に取得して使うものであって、直接変更するのは推奨されていないようです。
Quaternion は結構ややこしくて、まだまだ勉強中です。いつか分かる日が来るのだろうか…
下記記事が大変参考になったので記録として貼らせて頂きます。
参考 : 回転難しい
//ワールド座標の回転情報を取得 Quaternion q = transform.rotation;
Transform.localRotation
Transform.rotation のローカル座標バージョンです。
//ローカル座標の回転情報を取得 Quaternion q = transform.localRotation;
Transform.eulerAngles
ワールド座標におけるオブジェクトの回転情報を、オイラー角で格納する変数です。
これを使えば、内部的にはQuaternionで動いているRotationをオイラー角で取得したり、回転量を指定して回転させることができます。以下注意点はリファレンスより。
・回し続けたいときには非推奨。(後述 Rotate などを使う)
・インスペクター上で見る Rotation はローカル座標なので値が異なる場合がある。
//角度をワールド座標(0, 0, 0)に変更 transform.eulerAngles = new Vector3(0, 0, 0);
Transform.localEulerAngles
Transform.eulerAngles のローカル座標バージョンです。
//角度をローカル座標(0, 0, 0)に変更 transform.localEulerAngles = new Vector3(0, 0, 0);
スケール情報
Transform.localScale
インスペクター上で見るのと同じ、親を基準にしたローカルなスケール情報を格納する変数です。
private void Update() { //毎秒1ずつY軸スケールが大きくなる transform.localScale += new Vector3(0, 1, 0) * Time.deltaTime; }
ヒエラルキー上でのオブジェクトの階層情報
オブジェクトの親子関係のまとめ – Unity
親子関係に関する操作がまとまっている超良記事で、何度もお世話になりました。
「オブジェクトの階層情報」というよりも、正確には「Transformコンポーネント同士の階層情報」です。全オブジェクトにTransformコンポーネントが付いている為、オブジェクト同士の階層関係を参照・操作することができます。
Transform.root
そのオブジェクトの、一番上の親オブジェクトを取得します。
親がいない場合は自分自身が返ります。
//一番上の親を取得して格納 GameObject rootObj = this.gameObject.transform.root.gameObject;
Transform.parent
そのオブジェクトの、1階層上の親オブジェクトを取得します。
親の親は Transform.parent.parent となります。
親がいない場合は自分自身が返ります。
//1つ上の親を取得して格納 GameObject parentObj = this.gameObject.transform.parent.gameObject; //2つ上の親を取得して格納 GameObject grandParentObj = this.gameObject.transform.parent.parent.gameObject;
Transform.childCount
そのオブジェクトから見て1階層下の子オブジェクト数を取得します。
if 文で子の数に応じて処理を使い分ける実装などに使えます。
画像の赤い四角のオブジェクトにスクリプトをアタッチすると、青い範囲の子オブジェクトの数が返ります。
void Start() { Debug.Log(transform.childCount); }
Transform.hierarchyCount
そのオブジェクトの所属する階層のオブジェクト数を取得します。(自分自身も含む)
下記画像の青い範囲内のオブジェクトであれば、どこにスクリプトをアタッチしても同じ数が返ります。(この例では 8 )
void Start() { Debug.Log(transform.hierarchyCount); }
Transform のよく使う関数
位置情報・回転情報のワールド↔ローカル変換はあまり使わない気がするので触りだけにします。
もし使う機会があったら、勉強して書き加えたいと思います。
位置情報
Transform.TransformPoint(Vector3);
ローカル座標基準の位置情報を、ワールド座標に変換します。Vector3 で値が返ります。
Transform.InverseTransformPoint(Vector3);
ワールド座標基準の位置情報を、ローカル座標に変換します。Vector3 で値が返ります。
Transform.Translate(Vector3, Space);
移動させたい距離をVector3で引数に渡し、現在のPositionに加算させる関数です。
ローカル座標(Spase.Self)・ワールド座標(Spase.World) どちらを基準に動かすか、第2引数で指定できます。(何も指定しない場合はローカル座標)
private void Update() { if (Input.GetKey(KeyCode.UpArrow)) { //ローカル座標のY軸を毎秒+1する transform.Translate(0, 1 * Time.deltaTime, 0); } if (Input.GetKey(KeyCode.DownArrow)) { //ローカル座標のY軸を毎秒-1する transform.Translate(0, -1*Time.deltaTime, 0); } }
//ワールド座標を指定する場合の書き方 transform.Translate(0, 1, 0 , Space.World);
回転情報
Transform.TransformDirection(Vector3);
ローカル座標基準の回転情報を、ワールド座標に変換します。Vector3 で値が返ります。
Transform.InverseTransformDirection(Vector3);
ワールド座標基準の回転情報を、ローカル座標に変換します。Vector3 で値が返ります。
Transform.Rotate(Vector3 eulers, Space);
引数で渡した角度を現在の角度に加算し、回転させる関数です。オイラー角で回転量を指定します。
ローカル座標(Spase.Self)・ワールド座標(Spase.World) どちらを基準に回転させるかは、第2引数で指定できます。(何も指定しない場合はローカル座標)
private void Update() { //Z軸のRotationが毎秒+10される transform.Rotate(0, 0, 10 * Time.deltaTime); }
Transform.RotatoAround(Vector3 point, Vector3 axis, float angle);
ある座標を中心として、その周りを回転させます。
point には「回転の中心地点の位置ベクトル」、axis には「回転軸の方向ベクトル」、angle には「毎フレーム回転する角度」を引数として渡します。
void Update() { // 回転の中心位置 Vector3 point = new Vector3(0, 0, 0); // 回転軸の向き Vector3 axis = Vector3.up; // 毎フレーム回転する角度 var angle = 1; transform.RotateAround(point, axis, angle); }
Transform.LookAt(target);
対象のオブジェクトの方を向かせる関数です。引数でターゲットとなるオブジェクトのTransformを渡すと、Z軸が回転してターゲットの方を向きます。
public Transform target; void Update() { transform.LookAt(target); }
ヒエラルキー上でのオブジェクトの階層情報
Transform.Find(string);
GameObject.Find はヒエラルキー全体から検索するのに対し、Transform.Find は「指定したオブジェクトの子オブジェクトの中から検索」です。
GameObject.Find と違って 非アクティブなGameObjectも検索することができる点も大きな違いです。
使い方を真面目に書くと長くなるので省略しますが、筆者は最近はほとんど使わなくなりました。
重い処理なので避けられる場合は避けて実装します。
何度も見に行った良記事を参考に貼らせて頂きます。
参考 :
【初心者Unity】Transform.Findとは?GameObject.Findとの違いは?
【Unity入門】3分でわかるオブジェクト検索方法!Findを使いこなせ!
void Start() { Transform child = this.transform.Find("Child"); Debug.Log(child); }
Transform.GetChild(int);
引数に int を渡し、「1つ下の階層の子オブジェクトのうち○番目」を取得します。配列と同じで(0)が1番目の子オブジェクトとなります。
存在しないオブジェクトを参照するとエラーになるので注意。childCount を併せて使うなどして子オブジェクトの数を確認しながら使うと安全です。
下記の例は、1つ下の階層の子オブジェクトを全て取得する例です。(孫オブジェクトを含まない)
孫まで取得したい場合は Component.GetComponentsInChildren() を使う等、他の手法を取ります。
下記記事が大変参考になったので記録として貼らせて頂きます。
参考 : 【Unity】子オブジェクトを列挙(全取得)する
void Start() { //自分の子オブジェクトを格納する配列を作成 Transform[] children = new Transform[this.transform.childCount]; //自分自身のchildの数だけループ処理 for(int i = 0; i < transform.childCount; i++) { //配列「children」に格納 children[i] = transform.GetChild(i); //格納後、色々な処理に使える Debug.Log(children[i].name + children[i].position); } }
Transform.SetParent(Transform , bool);
そのオブジェクトを、第1引数に渡したTransformの直下の子にする関数です。
第2引数では「ワールド座標で見た子オブジェクトの位置・回転・スケール情報を引き継ぐか否か」を渡します。(指定しない場合はtrue)
true ならばワールド座標での情報を引き継ぐので、子になってもワールド座標で見た場合の位置・回転・スケールは動きません。
false ならば親のTransformから見たローカルな位置・回転・スケール情報に変換されます。ほとんどの場合 false を使います。
public Transform parent; void Start() { //自分自身を「parent」直下の子にする transform.SetParent(parent, false); }
Transform.DetachChildren();
そのオブジェクトの全ての子オブジェクトを、一括で子から解除する関数です。
void Start() { transform.DetachChildren(); }
Transform.IsChildOf(Transform);
あるオブジェクトが自分自身の親なのか否かをBoolで取得できます。
画像の赤い四角のオブジェクトに下記スクリプトをアタッチすると、青い範囲のオブジェクトでは true 、それ以外では false を返します。自分自身をチェックしてもtrue が返る点は注意が必要です。
public Transform checkTransform; void Start() { //自分自身から見て、checkTransform にアタッチしたTransformが親なのか否か Debug.Log(transform.IsChildOf(checkTransform)); }
Transform.SetAsFirstSibling();
ここから3つ続く SetSibling 系関数は、子要素同士(兄弟オブジェクト)の並べ替えに関するものです。特にUIにおいては並び順がレンダリングに大きく影響するので、子要素同士の順番を操作する場面が出てくるようです。
今回は触り程度にしますが、使う機会があったらまた書き加えたいと思います。
下記記事にて大変わかりやすくまとめて下さっています。
参考 : 【Unity】TransformのSetSibling系メソッドを使って要素の順番を変える
Transform.SetAsFirstSibling は、そのオブジェクトを兄弟オブジェクトの中で先頭へ並べ替える関数です。
Transform.SetAsLastSibling();
そのオブジェクトを兄弟オブジェクトの中で最後尾へ並べ替える関数です。
Transform.SetSiblingIndex(int);
引数に int を渡し、「兄弟オブジェクトの中で○番目へ並べ替える」関数です。
おわりに
いつも使っているTransformですが、掘り下げてみると便利機能が沢山ありますね。
また知識が増えたら追記しに来ます。今回はここまで!