结合使用MoveTowards和持续时间而不是速度 [英] Use MoveTowards with duration instead of speed

查看:500
本文介绍了结合使用MoveTowards和持续时间而不是速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要使用GameObject 从位置A移到位置B > Vector3.MoveTowards 在x秒内并在协程函数中.我知道如何使用 Vector3.Lerp 做到这一点,但是这次我更喜欢用Vector3.MoveTowards进行操作,因为两个函数的行为都不同.

I want to move GameObject from position A to B with Vector3.MoveTowards within x seconds and in a coroutine function. I know how to do this with Vector3.Lerp but this time would prefer to do it with Vector3.MoveTowards since both functions behave differently.

使用Vector3.Lerp,就像一样:

With Vector3.Lerp, this is done like this:

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的末尾.

I tried to do the the-same thing with Vector3.MoveTowards, but it's not working properly. The problem is that the move finishes before the x time or duration. Also, it doesn't move smoothly. It jumps to the middle of both positions than to the end of position B.

这是将Vector3.MoveTowards用于上述问题的函数:

This is the function that uses Vector3.MoveTowards with the issue above:

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秒内并启用协程功能?

How do you move GameObject from position A to B with Vector3.MoveTowards within x seconds and in a coroutine function?

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

Please do not suggest Vector3.Lerp as that's not what I want to use.

编辑:

替换

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

使用

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

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

works but introduces a problem when focus is shifted from Unity to another application. Doing that causes the movement to not finish. Calculating it every frame instead of once before starting the timer seems more reasonable.

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

MatrixTai's answer fixed both problems.

推荐答案

由于我很长时间没有接触Unity ...,但我确实相信您会弄乱计算.

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

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

每帧移动时从currentPostoPosition步行 一定距离time.

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

因此,使用time作为名称会造成混淆,但是可以保留它.

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

但是,您会在语句中注意到,time是每帧都在移动的内容.但是Vector3.Distance(currentPos, toPosition) / duration是速度(m/s),而不是(m/frame).要使其达到(m/frame),只需将Time.deltatime乘以(s/frame).

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).

第二,

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

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.

更具体地说,我们可以做一些数学运算.通常,这应该使用微积分来完成,但是通过仅考虑2点来简化它.当对象位置d = 0且对象位置d〜= 9.9时,假定端点为10.

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.

在点1,对象具有time =(10-0)/持续时间,全速. 在第2点,对象的time =(10-9.9)/持续时间,全速的1/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.

除非您希望它每帧移动得慢一些,否则您不能保持duration的值不变.就像在每一帧之后一样,要保持速度不变,持续时间应随距离而减小.

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.

所以最终的解决方案是

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

这是完整的功能:

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;
    }
}

这篇关于结合使用MoveTowards和持续时间而不是速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆