【Unity基礎】translateを使用してオブジェクトを動かす方法

オブジェクトに移動量を指定して動かす「Translate」について説明します。
Unityでオブジェクトを動かすには様々な方法がありますが、「Translate」による移動は、「Position」を使用した方法と同じく基本中の基本となります。

Translateの特徴、使いどころ

Translateではどのようにオブジェクトを動かすかと言うと、相対的な位置を指定して移動する、と言う方法です。
つまり、現在位置より前や右に0.5進む、と言った具合に直感的に指定できます。

このときの「前」というのは、オブジェクトから見て前(Z軸方向)と言う意味です。
つまり、オブジェクトが回転していたらオブジェクトの向いている方向に進みます。

positionやその他の動かし方に比べて、スクリプトの書き方がスッキリしてるので気軽に実装できます。
ただ、物理演算によって動きが計算されるRigidbodyオブジェクトに使うと、ややリアルさに欠ける動きになりがち。
というのも、現実世界では重いものほど動かすのに大きな力が必要ですが、Translateによる移動はオブジェクトの質量に関係なく動かせてしまうからです。

Transform.Translateの書式

Translateをスクリプトに記述するときの書式は次の2種類あります。

transform.Translate (Vector3 translation, Space relativeTo= Space.Self);
transform.Translate (float x, float y, float z, Space relativeTo= Space.Self);

移動量を指定するのにVector3を与えるか、x, y , zそれぞれの座標の数値を与えるかの違いです。

「Space」は、Translateで移動させるときの座標系を選択できます。
デフォルトで「Space.Self」となっていますが、これはオブジェクトのローカル座標を使用するという意味。
つまり、オブジェクトが回転していたら、その向きに進行方向が影響を受けます。

この引数は省略可能で、省略した場合は「Space.Self」と書くのと同じ意味になります。
引数に「Space.World」を与えた場合はワールド座標を使用することになり、オブジェクトの向きに関係なく動かせます。

Transform.Translateのスクリプト例

スクリプトのUpdateに下記をコピペし、オブジェクトにアタッチするとキー操作で動かせます。

void Update() { 
    //  Upキーで前に進む 
    if (Input.GetKey("up")) { 
        transform.Translate(0, 0, 0.1f, Space.Self); 
    } 
    // Downキーで後ろに進む 
    if (Input.GetKey("down")) { 
        transform.Translate(0, 0, -0.1f, Space.Self); 
    } 
    //right キーで右に進む 
    if (Input.GetKey("right")) { 
        transform.Translate(0.1f, 0, 0, Space.Self); 
    } 
    //left キーで左に進む 
    if (Input.GetKey("left")) { 
        transform.Translate(-0.1f, 0, 0, Space.Self); 
    } 
    //Aキーで左回転 
    if (Input.GetKey("a")) { 
        transform.Rotate(new Vector3(0, -2.0f, 0)); 
    } 
    //Sキーで右回転 
    if (Input.GetKey("s")) { 
        transform.Rotate(new Vector3(0, 2.0f, 0)); 
    } 
} 

Spaceについて

Spaceを「Self」または「World」にしたときの挙動の違いです。
オブジェクトが斜めを向いている場合、「Self」はオブジェクトから見て前の方向に進むのに対し、「World」はワールド座標のZ軸方向に進んでいます。

それぞれのキューブは下記のスクリプトで動いています。

void Update() { 
    transform.Translate(0, 0, 0.1f, Space.Self); 
} 
void Update() { 
    transform.Translate(0, 0, 0.1f, Space.World); 
} 

動きが速いとすり抜ける

transform.positionで動かす場合も同じですが、transform.Translateで動かす場合も動きが早いと間のオブジェクトをすり抜ける減少が起こります。
上の画像はTranslateで左右に3ずつ行ったり来たりしていますが、あいだのキューブには接触せずにすり抜けています。

このことから、Translateでは指定した距離を瞬間移動していて、間にある物体には影響を及ぼさない事が分かります。
弾丸を超高速で発射するような場面では、目標に当たらずにすり抜ける可能性があるので、Translateの使用には注意が必要です。

対策としては、Rgidbody.MovePositionを使ったり、Rigidbody.AddForceを使うことが考えられます。

 

positionとTranslateの違い

transform.positionは絶対的な指定位置への移動、Translateは現在位置から見た相対的な位置を指定しての移動と言う違いがあります。
しかしスクリプトの書き方次第では上の画像の例のように、positionを使ってTranslateと同じ動きを実装することは可能です。

void Update() { 
    transform.Rotate(new Vector3(0, 2.0f, 0)); 
    //  Upキーで前に進む 
    if (Input.GetKey("up")) { 
        transform.Translate(0, 0, 0.1f); 
} 
void Update() { 
    transform.Rotate(new Vector3(0, 2.0f, 0)); 
    //  Upキーで前に進む 
    if (Input.GetKey("up")) { 
        transform.position += transform.forward * 0.1f; 
    } 
} 

Unityで同じことを実現するにしても、色々なやり方があるよと言う参考例でした。

コメント