【Unity】オブジェクトの移動|Transformの使い方

moving Unity development

オブジェクトを移動する方法が知りたいのですが…

Vector3を使った直線移動の方法について解説していきます。

完成イメージ

下準備

以下の流れで作業を進めていきます。

  1. Projectを開く
  2. オブジェクト[Cube]と[Sphere]を配置
  3. オブジェクト[Cube]と[Sphere]に色を追加
  4. オブジェクト[Sphere]にScriptを追加

▼ここでの操作方法に不安のある方は、こちらをご参照ください▼

完成イメージは以下のようになります。(具体的なパラメータは以下で解説)

1-Prepare

オブジェクトの配置

解説画面と合わせるために、以下のように各オブジェクトの配置や名前を変更をしていきます。

[Cube]は、オブジェクト名を[Ground]に変更し、[Transform]を以下のように変更します。

3-name-Transform-change

[Sphere]は、オブジェクト名を[missile]に変更し、[Transform]を以下のように変更します。

5-missile-add

マテリアルの設定

各オブジェクトのMaterial名を設定します。

Material名は、
[Cube]→[GroundMat]、[Sphere]→[MissileMat]に変更します。

7-Material-name-change

Main Cameraの設定

GameビューでScene全体が見えるように、Main Cameraを設定します。

[Main Camera]を選択し、Inspectorウインドウの[Transform]を以下のように変更します。

11-2-Camera-angle

Scriptの追加

オブジェクト[Missile]に制御するためのScriptを追加します。

Script名は、[Missile_move]に変更しています。

15-Script-add4

Scriptの追加が完了すると、このようになります。

15−1-Script-add5

目標位置への配置

Scriptを編集して、オブジェクトを制御します。

projectウインドウのScript[Missile_move]をクリックして開きます。

現在位置から目標位置に配置するScriptを作成します。

Script

ProjectウインドウのScript[Missile_move]をクリックして開きます。

Vector3型の変数targetを宣言し、Start( )メソッドで指定の位置に配置させるScriptです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{
    //Vector3型の変数targetを宣言
    //newでfloat型(f)の初期値を代入
    public Vector3 target = new Vector3(4.0f, 0.0f, 8.0f);

    // Start is called before the first frame update
    void Start()
    {
     //オブジェクトを移動させる命令(引数に距離を指定)
        this.transform.Translate(target);
    }

    // Update is called once per frame
    void Update()
    {
       
    }
}

編集が完了したら、保存します。

動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。

指定した位置にオブジェクトが配置されます。

18-gameplay

無限位置への移動

ベクトル量をUpdateメソッドで更新しながら加算していくことで、オブジェクトが無限に進むScriptを作成していきます。ここでは、ベクトル量の違う2つのオブジェクトを比較しながら確認していきます。

オブジェクトの複製

Scriptの内容を深めるために、ベクトル量の違う[Missile]を複製します。

[Missile]が複製されて、[Missile(1)]が作成されますので、Inspectorウインドウの[Transform]と[Target]を以下のように変更します。

オブジェクトの複製は、Hierarchyウインドウの[Missile]を選択して、[Ctrlキー]+[D]もしくは、[Commandキー]+[D]をクリックします。

23-Duplicate

ベクトル量で速度調整

現在位置から無限に進むScriptを作成します。
ここでは、指定するベクトル量に応じて速度を可変するパターンを解説します。

Script

更新が発生するたびに、ベクトルが加算されていくScriptを作成します。

Startメソッドにfloat型の倍数をかけて、速度を調整できるようにします。また、端末のスペックに関係なく、1秒間(時間基準)で進む距離を規定するため、”Time.deltaTime”を乗算しています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{
    //Vector3型の変数targetを宣言
    //newでfloat型(f)の初期値を代入
    public Vector3 target = new Vector3(4.0f, 2.0f, 8.0f);

    // Start is called before the first frame update
    void Start()
    {
    //単位時間に進む量(target)に倍数をかけて、速度を調整
    target = target * 0.01f;
    }

    // Update is called once per frame
    void Update()
    {
        //オブジェクトを移動させる命令(引数に距離を指定)
        this.transform.Translate(target * Time.deltaTime);      
    }
}

編集が完了したら、保存します。

動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。
[Missile(1)]が[Missile]を追い抜いています。

これは、大きなベクトル(targetの値)を設定した[Missile(1)]の方が単位時間当たりの移動量が大きくなるためです。

実行中の[Missile]のInspectorウインドウの[Transform]を確認すると、[Position]の値が増えていくのがわかります。時間を追うごとにどこまでも進んでいきます。

21-gameplay2

ベクトル量に関わらず速度一定

Script

今度は、ベクトル量に関わらず、[Missile]と[Missile(1)]を速度を同じにしていきます。

normalizedを使用して、正規化して長さが1のベクトルを設定することで解決します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{
    //Vector3型の変数targetを宣言
    //newでfloat型(f)の初期値を代入
    public Vector3 target = new Vector3(4.0f, 2.0f, 8.0f);
  public float speed = 1.0f;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        //オブジェクトを移動させる命令(引数に距離を指定)
        this.transform.Translate(target.normalized * speed * Time.deltaTime);      
    }
}

編集が完了したら保存します。

public変数に指定したspeedをInspectorウインドウから変更します。

26-speed-change
動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。

狙い通り、[Missile(1)]と[Missile]が同じ速度で動きます。

目標物への追従(直線的)

オブジェクトが狙ったオブジェクトに向かっていくScriptを作成します。

目標物の作成

配置

Hierarchyウインドウ下の[+]>[3D Object]>[Cylinder]の順にクリックします。
オブジェクト名を[Pole]に変更し、[Transform]を以下のように設定します。

1-Pole-add

Script

オブジェクト[Pole]をキーボードの矢印キーで移動させるScript[Pole_move]を追加します。
Projectウインドウに追加したら、クリックして開きます。

キーボードの[↑↓→←]でオブジェクトを移動させるScriptを書いていきます。

using UnityEngine;
using System.Collections;

public class Pole_move : MonoBehaviour
{
    //速度調整用の変数
    public float speed = 10.0f;

    void Update()
    {
        //前後移動(キーボード入力値)
        float translationV = Input.GetAxis("Vertical") * speed;
        //左右移動(キーボード入力値)
        float translationH = Input.GetAxis("Horizontal") * speed;

        //端末スペックに依存しない設定
        translationV *= Time.deltaTime;
        translationH *= Time.deltaTime;

        //キーボード入力値に応じてオブジェクトを移動させる
        transform.Translate(translationH, 0, translationV);
    }
}

編集が完了したら、保存します。
以下のようになっていれば完了です。

pole-move-script

カメラの配置

Hierarchyウインドウの[Main Camera]を選択し、Inspectorウインドウの[Transform]を以下のように設定します。

2-camera-position

ここまでの設定で、以下のようになります。

3-gameview

Script

目標物を追従するScriptを作成します。
ProjectウインドウのScript[Misslile_move]を開きます。

[Pole]と[Missile]の相対距離を計算して、その距離を目標として[Missile]が進む。目標は常にUpdateメソッドで更新していくため、徐々に小さくなり、[Pole]に到達する。

Startメソッドに”LookAt”を追加することで、[Pole]の方向に向きを変えます。
“Space.World”は、ワールド座標(絶対座標)を意味します。(対義語:相対座標 ”Space.Self”)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{

    //public変数を宣言
    public float speed = 2.0f;
    public Transform pole;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void LateUpdate()
    {
    //poleの位置を取得して、その方向を向く
        this.transform.LookAt(pole.position);

        //this=Missileとpole=Poleの位置の差を計算
        Vector3 target = pole.position - this.transform.position;

        //オブジェクトを移動させる命令(位置の差分移動する)
        this.transform.Translate(target.normalized * speed * Time.deltaTime, Space.World);

    }
}

編集が完了したら、保存します。

Hierarchyウインドウの[Missile]を選択肢し、Inspectorウインドウの[Pole]の欄に、Hierarchyウインドウの[Pole]をドラッグして離します。

動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。
目標物の[Pole]を目掛けて、[Missile]が飛んでいきます。

上の動画では表現できていませんが、Gameビューでは、[Missile]が[Pole]に衝突してから、振動しています。これは、相対距離ベクトルが厳密に0(ゼロ)にならないために起こっている現象です。

Scriptの修正

相対距離ベクトルが厳密に0(ゼロ)にならないのであれば、if文で小さい値になったら、衝突をやめるという命令に書き換えます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{

    //public変数を宣言
    public float speed = 2.0f;
    public Transform pole;
    public float nearly = 0.1f;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void LateUpdate()
    {

        //poleの位置を取得して、その方向を向く
        this.transform.LookAt(pole.position);

        //this=Missileとpole=Poleの位置の差を計算
        Vector3 target = pole.position - this.transform.position;

        //MissileとPoleの距離がnearly以上の場合にオブジェクトを移動
        if(target.magnitude > nearly)

        //オブジェクトを移動させる命令(位置の差分移動する)
        this.transform.Translate(target.normalized * speed * Time.deltaTime,Space.World);


    }
}

動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。
無事に振動が解決できました。

ちなみに、Y軸の方向へも追従します。

目標物への追従(曲線的)

Script

曲線的に遊びを持った追従の仕方を解説します。

”Quaternion Slerp”は、指定した区間を球状に補間します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Missile_move : MonoBehaviour
{

    //public変数を宣言
    public float speed = 2.0f;
    public Transform pole;
    public float nearly = 0.1f;
    public float rotSpeed = 1.0f;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void LateUpdate()
    {

        //poleのx,z座標とmissileのy座標をlookAtPoalに代入
        Vector3 lookAtPoal = new Vector3(pole.position.x,
                                     this.transform.position.y,
                                     pole.position.z);

        //poleとmissileの位置の差をdirectionに代入
        Vector3 direction = lookAtPoal - this.transform.position;

        this.transform.rotation = Quaternion.Slerp
                                    (this.transform.rotation,
                                    Quaternion.LookRotation(direction),
                                     Time.deltaTime * rotSpeed);

        //MissileとPoleの距離がnearly以上の場合にオブジェクトを移動
        if (Vector3.Distance(transform.position, lookAtPoal) > nearly)

            //オブジェクトを移動させる命令
            //オブジェクトの方向を向いているので、前進・後退はz座標で指定
            this.transform.Translate(0, 0, speed * Time.deltaTime);

    }
}

動作確認

[▶︎]ゲームプレイをクリックして動作を確認します。
曲線的に遊びを持ちながら追従していきます。

以上です。お疲れ様でした。

▼ポチッと応援お願いします▼
にほんブログ村 IT技術ブログ Unityへ
にほんブログ村
タイトルとURLをコピーしました