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

Pro*_*mer 3 c# unity-game-engine lerp

我想在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图做同样的事情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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

请不要暗示,Vector3.Lerp因为那不是我想要使用的.

编辑:

更换

float time = Vector3.Distance(currentPos, toPosition) / duration;
Run Code Online (Sandbox Code Playgroud)

float time = Vector3.Distance(startPos, toPosition) / (duration * 60f);
Run Code Online (Sandbox Code Playgroud)

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

MatrixTai的答案解决了这两个问题.

MT-*_*ong 5

因为我很久没有接触过Unity ......但我确实相信你搞砸了计算.

首先,Vector3.MoveTowards(currentPos, toPosition, time)正在谈论

从步行currentPostoPosition与每个帧中移动一定的距离time.

因此使用time名称令人困惑,但很好,让我们保持它.

但是,您会在声明中注意到,time每个帧都会移动.但是Vector3.Distance(currentPos, toPosition) / duration速度(m/s),而不是(m /帧).为了使它(m /帧),简单的时间Time.deltatime是(s /帧).

其次,

在协程中,这意味着每个帧都迭代了函数.在这一行中float time = Vector3.Distance(currentPos, toPosition) / duration * Time.deltatime;,你会注意到time随着距离变得越来越小,下一帧时继续减少.

更具体一点,我们可以做一些数学计算.通常这应该用微积分来完成,但我们只需考虑2个点就可以简化它.当对象位置d = 0,并且对象位置d~ = 9.9时,假设端点为10.

在点1处,对象具有time=(10-0)/持续时间,全速.在点2处,对象具有time=(10-9.9)/持续时间,全速的1/10.

除非你希望它每帧都移动得慢,否则你不能保持持续时间的值不变.在每帧之后,您希望保持速度,因此持续时间应随距离而减小.

使物理工作,减去时间的持续时间.

所以最终的解决方案是

float time = Vector3.Distance(currentPos, toPosition) / (duration-counter) * Time.deltaTime;
Run Code Online (Sandbox Code Playgroud)

这是完整的功能:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)