猿问

使用带有持续时间而不是速度的 MoveTowards

我想在 x 秒内并在协程函数中将GameObject从位置 A移动到 B。Vector3.MoveTowards我知道如何做到这一点,Vector3.Lerp但这次更愿意这样做,Vector3.MoveTowards因为这两个函数的行为不同。


有了Vector3.Lerp,这就像做这个:


IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration)

{

    float counter = 0;


    //Get the current position of the object to be moved

    Vector3 startPos = fromPosition.position;


    while (counter < duration)

    {

        counter += Time.deltaTime;

        fromPosition.position = Vector3.Lerp(startPos, toPosition, counter / duration);

        yield return null;

    }

}

我试图用 做同样的事情Vector3.MoveTowards,但它不能正常工作。问题是移动在 x 时间或持续时间之前完成。此外,它不会平稳移动。它跳到两个位置的中间而不是位置 B 的末尾。


这是Vector3.MoveTowards与上述问题一起使用的函数:


IEnumerator MoveTowards(Transform objectToMove, Vector3 toPosition, float duration)

{

    float counter = 0;


    while (counter < duration)

    {

        counter += Time.deltaTime;

        Vector3 currentPos = objectToMove.position;

        float time = Vector3.Distance(currentPos, toPosition) / duration;


        objectToMove.position = Vector3.MoveTowards(currentPos, toPosition,

         time);


        Debug.Log(counter + " / " + duration);

        yield return null;

    }

}

如何Vector3.MoveTowards在 x 秒内并在协程函数中将GameObject 从位置 A 移动到 B ?


请不要建议,Vector3.Lerp因为那不是我想要使用的。


编辑:


更换


float time = Vector3.Distance(currentPos, toPosition) / duration;


float time = Vector3.Distance(startPos, toPosition) / (duration * 60f);

工作,但当焦点从 Unity 转移到另一个应用程序时会出现问题。这样做会导致运动无法完成。在启动计时器之前每帧计算一次而不是一次似乎更合理。


萧十郎
浏览 345回答 1
1回答

MYYA

因为我很长时间没有接触过 Unity ......但我相信你在计算中搞砸了。首先,Vector3.MoveTowards(currentPos, toPosition, time)正在谈论每帧从currentPos到toPosition移动一定距离time。因此使用timeas name 是令人困惑的,但很好,让我们保留它。然而,你会注意到在语句中,time每帧都是移动的东西。但是Vector3.Distance(currentPos, toPosition) / duration是速度(m/s),而不是(m/frame)。要使其(m/frame),只需乘以Time.deltatime(s/frame)即可。其次,在协程中时,这意味着该函数在每一帧中进行迭代。在该行中float time = Vector3.Distance(currentPos, toPosition) / duration * Time.deltatime;,您会注意到time随着距离越来越小,在下一帧时不断减少。更具体地说,我们可以做一些数学运算。通常这应该用微积分来完成,但让我们通过只考虑 2 点来简化它。当对象位置 d = 0 且对象位置 d ~= 9.9 时,假设端点为 10。在点 1 处,对象具有time= (10-0)/duration,全速。在第 2 点,物体有time= (10-9.9)/duration,全速的 1/10。除非您希望它每帧移动得更慢,否则您不能保持持续时间的值不变。由于在每一帧之后,您希望保持速度,因此持续时间应该随着距离的增加而减少。为了使物理起作用,减去经过的时间的持续时间。所以最终的解决方案是float time = Vector3.Distance(currentPos, toPosition) / (duration-counter) * Time.deltaTime;这是完整的功能:IEnumerator MoveTowards(Transform objectToMove, Vector3 toPosition, float duration){&nbsp; &nbsp; float counter = 0;&nbsp; &nbsp; while (counter < duration)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; counter += Time.deltaTime;&nbsp; &nbsp; &nbsp; &nbsp; Vector3 currentPos = objectToMove.position;&nbsp; &nbsp; &nbsp; &nbsp; float time = Vector3.Distance(currentPos, toPosition) / (duration - counter) * Time.deltaTime;&nbsp; &nbsp; &nbsp; &nbsp; objectToMove.position = Vector3.MoveTowards(currentPos, toPosition, time);&nbsp; &nbsp; &nbsp; &nbsp; Debug.Log(counter + " / " + duration);&nbsp; &nbsp; &nbsp; &nbsp; yield return null;&nbsp; &nbsp; }}
随时随地看视频慕课网APP
我要回答