我只是提出自己的想法,或許有更好的做法可以解決這個問題,不一定要按照我這個方式做。
要讓物件能在3D模式下等速移動,我們需要用到下面兩個Vector3的Method:
不過由於Lerp會不斷地重新計算「從當前物件到目標物件」之間的距離,會導致物件移動越來越慢,所以我們需要在物件Lerp移動過後重新計算移動速度。
要求:
假設 PathA 的座標為(0, 0, 0)
PathB 的座標為(0, 10, 0)
speed為0.1
有個物件 Obj 要從PathA 移動到 PathB
解答:
speed = 0.1
代表 PathA 到 PathB 之間的移動都會以每次 0.1 為單位,也就是說 PathA 到 PathB 之間被分割成了10等分,即可得知移動的分割大小為 PathA 到 PathB 之間的距離乘上 speed。
而要等速移動的話,則要確保物件每Lerp移動過後,下次的距離分割要和第一個距離分割相等,如此可寫出一個公式:speed = firstSpeed / Distance(PathA, PathB)
上面的觀念理解之後,就可以開始來撰寫程式碼了!
建立如下物件
各物件Transform參數如下
然後新增一個 C# script ,命名為Move,並撰寫以下程式碼
using UnityEngine;
public class Move : MonoBehaviour
{
public GameObject PathA;//起點
public GameObject PathB;//終點
public GameObject Obj;//要移動的物件
public float speed = 0.2f;//移動速度
private float firstSpeed;//紀錄第一次移動的距離
private void Start()
{
// PathA 和 PathB 的距離乘上 speed
firstSpeed = Vector3.Distance(Obj.transform.position, PathB.transform.position) * speed;
}
private void Update ()
{
//讓使用者每按一次 ↑ 時都移動一次,這只是為了方便看出每次移動的距離
if (Input.GetKeyDown(KeyCode.UpArrow))
{
//先移動過後,再計算新的 speed
Obj.transform.position = Vector3.Lerp(Obj.transform.position, PathB.transform.position, speed);
speed = calculateNewSpeed();
}
}
private float calculateNewSpeed()
{
//因為每次移動都是 Obj 在移動,所以要取得 Obj 和 PathB 的距離
float tmp = Vector3.Distance(Obj.transform.position, PathB.transform.position);
//當距離為0的時候,就代表已經移動到目的地了。
if (tmp == 0)
return tmp;
else
return (firstSpeed / tmp);
}
}
我將腳本放到Camera上,然後將各物件都拖曳到指定位置
按下執行!然後觀察 Cube 的Transform,可以發現Cube每次移動都是等距的(可以點選Camera看每次speed的改變)
剛執行時:
按了一次 ↑ 時:
按了二次 ↑ 時:
按了三次 ↑ 時:
按了四次 ↑ 時:
按了五次 ↑ 時:
因為已經到達指定的位置,所以不管再按幾次 ↑ 都不會移動了。
P.S.1.可以使用步進的方式取代按鍵
P.S.2.可搭配Time.deltaTime,讓移動更平順
留言列表