オブジェクトを移動する方法が知りたいのですが…
Vector3を使った直線移動の方法について解説していきます。
完成イメージ
下準備
以下の流れで作業を進めていきます。
- Projectを開く
- オブジェクト[Cube]と[Sphere]を配置
- オブジェクト[Cube]と[Sphere]に色を追加
- オブジェクト[Sphere]にScriptを追加
▼ここでの操作方法に不安のある方は、こちらをご参照ください▼
完成イメージは以下のようになります。(具体的なパラメータは以下で解説)
オブジェクトの配置
解説画面と合わせるために、以下のように各オブジェクトの配置や名前を変更をしていきます。
[Cube]は、オブジェクト名を[Ground]に変更し、[Transform]を以下のように変更します。
[Sphere]は、オブジェクト名を[missile]に変更し、[Transform]を以下のように変更します。
マテリアルの設定
各オブジェクトのMaterial名を設定します。
Material名は、
[Cube]→[GroundMat]、[Sphere]→[MissileMat]に変更します。
Main Cameraの設定
GameビューでScene全体が見えるように、Main Cameraを設定します。
[Main Camera]を選択し、Inspectorウインドウの[Transform]を以下のように変更します。
Scriptの追加
オブジェクト[Missile]に制御するためのScriptを追加します。
Script名は、[Missile_move]に変更しています。
Scriptの追加が完了すると、このようになります。
目標位置への配置
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()
{
}
}
編集が完了したら、保存します。
動作確認
[▶︎]ゲームプレイをクリックして動作を確認します。
指定した位置にオブジェクトが配置されます。
無限位置への移動
ベクトル量をUpdateメソッドで更新しながら加算していくことで、オブジェクトが無限に進むScriptを作成していきます。ここでは、ベクトル量の違う2つのオブジェクトを比較しながら確認していきます。
オブジェクトの複製
Scriptの内容を深めるために、ベクトル量の違う[Missile]を複製します。
[Missile]が複製されて、[Missile(1)]が作成されますので、Inspectorウインドウの[Transform]と[Target]を以下のように変更します。
オブジェクトの複製は、Hierarchyウインドウの[Missile]を選択して、[Ctrlキー]+[D]もしくは、[Commandキー]+[D]をクリックします。
ベクトル量で速度調整
現在位置から無限に進む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]の値が増えていくのがわかります。時間を追うごとにどこまでも進んでいきます。
ベクトル量に関わらず速度一定
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ウインドウから変更します。
動作確認
[▶︎]ゲームプレイをクリックして動作を確認します。
狙い通り、[Missile(1)]と[Missile]が同じ速度で動きます。
目標物への追従(直線的)
オブジェクトが狙ったオブジェクトに向かっていくScriptを作成します。
目標物の作成
配置
Hierarchyウインドウ下の[+]>[3D Object]>[Cylinder]の順にクリックします。
オブジェクト名を[Pole]に変更し、[Transform]を以下のように設定します。
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);
}
}
編集が完了したら、保存します。
以下のようになっていれば完了です。
カメラの配置
Hierarchyウインドウの[Main Camera]を選択し、Inspectorウインドウの[Transform]を以下のように設定します。
ここまでの設定で、以下のようになります。
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);
}
}
動作確認
[▶︎]ゲームプレイをクリックして動作を確認します。
曲線的に遊びを持ちながら追従していきます。
以上です。お疲れ様でした。