移動距離が変わっても、指定した速度で等速直線移動させたい
やりたいこと
・移動距離が変わっても、指定した速度で直線移動し、到達したら止まる。
魔法師の魔法攻撃処理で悩んだのでメモ。
全体の移動距離から1フレームの移動距離(つまり速度)を割り出す方法だと、等速で移動するけど移動距離によって速度が違ってきちゃう。
そうじゃなくて、移動距離が変わっても速度は指定したままで進んで欲しい。
使うメソッド
public static Vector3 MoveTowards (Vector3 current, Vector3 target, float maxDistanceDelta);
current
= 始点
target
= 終点
maxDistanceDelta
= 1フレームで進む距離
current
からtarget
に向かって、maxDistanceDelta
ずつ進む。
target
がmaxDistanceDelta
より近い場合は、target
の地点へ移動。つまり、target
を超えて進まない。
maxDistanceDelta
がマイナス値だと、target
と逆方向へ移動してしまうので注意。
コード
この場合のspeedは、全体の移動にかかる時間ではなく、1秒で進む距離のことになる。
数値が大きいほど早く移動する。
1秒間に何フレーム再生されるか(FPS)は不定なので、Time.deltaTimeで調整してくれている。
(ということだと思う。)
//移動速度 float speed = 2f; //標的 GameObject target; public void OnStart (GameObject target) { this.target = target; StartCoroutine (Throw ()); } IEnumerator Throw () { while (true) { transform.position = Vector3.MoveTowards (transform.position, target.transform.position, speed * Time.deltaTime); yield return null; } }
任意のタイミングでOnStart()を実行する。
到達したら消滅したい場合
距離が0.1f未満になったら、小さくなって破棄する。
transform.position == target.transform.position
この条件でも良さそうなんだけど、実行してみたらピッタリにならないようなので、少し余裕を持たせて0.1fにしてみた。
(おそらく、ピッタリにならないのはターゲットが移動しているせいだと思う。)
IEnumerator Throw () { while (true) { float distance = Vector3.Distance (transform.position, target.transform.position); if (distance < 0.1f) { StartCoroutine (Destroy ()); yield break; } speed = speed * stageManager.GetPlaySpeed (); transform.position = Vector3.MoveTowards (transform.position, target.transform.position, speed * Time.deltaTime); yield return null; } } IEnumerator Destroy () { while (true) { float speed = 6f * Time.deltaTime; gameObject.transform.localScale -= new Vector3 (speed, speed, speed); if (gameObject.transform.localScale.x <= 0f) { Destroy (gameObject); yield break; } yield return null; } }
以上。