トマシープが学ぶ

Unity/VR/AR/デザイン好きのミーハー 記事内容は自分用のメモです

【Lerp関数】キーを押したら1m先にすいーって動くスクリプト

Vector3-Lerp

移動の線形補完をしてくれるLerp。らーぷって読むのかな?

docs.unity3d.com

Vector3 Lerp(Vector3 a、 Vector3 b、float t);

Vector3.Lerp(始まりの位置, 終わりの位置, 現在の位置)

tの値が0~1に動くようにすると、a~bへ動くVector3の値が返ってくる

 tの値の変化

始まりの位置/終わりの位置は分かるけど、3つ目のfloatが分かりにくい。

0~1で変化するようにしないといけない。

 

公式リファレンスではこんな感じ

f:id:bibinbaleo:20200817134059p:plain

tの値を動かすのめっちゃ大変やん・・・

時間×速度=距離という学生の頃によく使った公式を思い出す必要がある!久しぶりすぎてそんな基礎的なことすら忘れてた。

 

実装している参考記事

ritsuka.dev

もしくはTimedeltaTime(*speed)で数字を増やしてもよい。1を超えた分は勝手に丸めてくれるみたい

daichitakezawa.hatenablog.com

Timedeltaを使う方法と公式リファレンスの方法、どう動きが違うんだろう?

キーを押したら動かす

キーを押したら、1m先にすいーって動くスクリプトを作ってみたい。

Lerp関数は、Updateなどずっと実行してくれるところに書かないといけない。

teratail.com

でもキーを押したらその中の処理をずっと実行ってどうやるんだっけ・・・?

コルーチンか??

コルーチンのUnity公式ドキュメントで、Input.GetKeyの中でFade処理をしている!

docs.unity3d.com

こちらのコルーチンを使ったスクリプトを使ったらできた!

qiita.com

こんな感じ!

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// reference:https://qiita.com/nekomimi-daimao/items/643890aed2178ee591a7
public class move : MonoBehaviour
{

    [SerializeField] private GameObject _Obj;
    [SerializeField] private float _TravelTime= 1.0f;
    [SerializeField] private float _Length = 1.0f;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Vector3 _nowPos = _Obj.transform.position;
            Vector3 _targetPos = new Vector3(_nowPos.x + _Length, _nowPos.y, _nowPos.z);
            StartCoroutine(AnimateCoroutine(_Obj.transform, _TravelTime, _targetPos, null));
        }
    }

    IEnumerator AnimateCoroutine(Transform transform, float time, Vector3? position, Quaternion? rotation)
    {
        // 現在のposition, rotation
        var currentPosition = transform.position;
        var currentRotation = transform.rotation;

        // 目標のposition, rotation
        var targetPosition = position ?? currentPosition;
        var targetRotation = rotation ?? currentRotation;

        var sumTime = 0f;
        while (true)
        {
            // Coroutine開始フレームから何秒経過したか
            sumTime += Time.deltaTime;
            // 指定された時間に対して経過した時間の割合
            var ratio = sumTime / time;

            transform.SetPositionAndRotation(
                Vector3.Lerp(currentPosition, targetPosition, ratio),
                Quaternion.Lerp(currentRotation, targetRotation, ratio)
            );

            if (ratio > 1.0f)
            {
                // 目標の値に到達したらこのCoroutineを終了する
                // ~.Lerpは割合を示す引数は0 ~ 1の間にClampされるので1より大きくても問題なし
                break;
            }

            yield return null;
        }
    }
}

目的地までの移動時間と移動する距離はインスペクタで設定。

f:id:bibinbaleo:20200817144131p:plain

これでできた!

f:id:bibinbaleo:20200817143652g:plain

 最後に

Lerp意外と奥が深かった

Lerp以外にも弧を描いて動くSlerpなどある

www.sejuku.net

 

f:id:bibinbaleo:20200817212125p:plain