Use MoveTowards with duration instead of speed

旧城冷巷雨未停 提交于 2019-12-01 22:34:54
MatrixTai

As I have long time not touching Unity... but I do believe you mess up in the calculation.

First of all, Vector3.MoveTowards(currentPos, toPosition, time) is talking about

Walking from currentPos to toPosition with each frame moving certain distance time.

Thus using time as name is confusing, but fine lets keep it.

However, you will notice in the statement, time is something move each frame. But Vector3.Distance(currentPos, toPosition) / duration is velocity (m/s), not (m/frame). To make it (m/frame), simply times Time.deltatime which is (s/frame).

Secondly,

When in coroutine, which means the function is iterated each frame. In the line float time = Vector3.Distance(currentPos, toPosition) / duration * Time.deltatime;, what you will notice is that the time keeps on decreasing when going next frame as distance become smaller and smaller.

To be more concrete, we can do some math. Typically this should be done with calculus, but lets simplify it by considering just 2 points. When object postion d = 0, and object postion d ~= 9.9, assume endpoint at 10.

At point 1, the object has time = (10-0)/duration, full speed. At point 2, the object has time = (10-9.9)/duration, 1/10 of full speed.

Unless you want it to move slower every frame, you cannot hold the value of duration unchanged. As after each frame, you want the velocity to be kept, duration should thus decreases with distance.

To make that physics work, minus the duration for the time passed.

So the final solution is

float time = Vector3.Distance(currentPos, toPosition) / (duration-counter) * Time.deltaTime;

Here is the complete function:

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 - counter) * Time.deltaTime;

        objectToMove.position = Vector3.MoveTowards(currentPos, toPosition, time);

        Debug.Log(counter + " / " + duration);
        yield return null;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!