close

我只是提出自己的想法,或許有更好的做法可以解決這個問題,不一定要按照我這個方式做。

 

 

 

 

要讓物件能在3D模式下等速移動,我們需要用到下面兩個Vector3的Method:

Lerp

Distance

 

不過由於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,讓移動更平順

arrow
arrow
    全站熱搜

    Yang 發表在 痞客邦 留言(0) 人氣()