为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
萧十郎 2021-09-19 15:54:10
我想在 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 转移到另一个应用程序时会出现问题。这样做会导致运动无法完成。在启动计时器之前每帧计算一次而不是一次似乎更合理。
查看完整描述

1 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

因为我很长时间没有接触过 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)

{

    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;

    }

}


查看完整回答
反对 回复 2021-09-19
  • 1 回答
  • 0 关注
  • 344 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信