C# 使用Vector2.MoveToward轻松进出

C# 使用Vector2.MoveToward轻松进出,c#,unity3d,C#,Unity3d,我已经看到了很多使用Vector2.Lerp轻松的例子 但我想使用向量2。移动到,因为我将我的NPC移动的距离随机化,我希望NPC的速度始终保持不变,而不管移动的距离。理想情况下,如果可能的话,我想用动画曲线来控制放松,但是平滑步长功能也可以。下面是我现在使用的简化代码(使用行为设计器,因此方法有点不同): 好的,第一个问题是:永远不要使用=来比较两个浮点值 甚至像5f*0.2f/10f==1f这样的情况也可能失败,因为由于浮点精度的原因,它实际上可能是0.999999或1.0000001 相反

我已经看到了很多使用
Vector2.Lerp
轻松的例子

但我想使用向量2。移动到,因为我将我的NPC移动的距离随机化,我希望NPC的速度始终保持不变,而不管移动的距离。理想情况下,如果可能的话,我想用
动画曲线
来控制放松,但是平滑步长功能也可以。下面是我现在使用的简化代码(使用行为设计器,因此方法有点不同):


好的,第一个问题是:永远不要使用
=
来比较两个
浮点值

甚至像
5f*0.2f/10f==1f
这样的情况也可能失败,因为由于浮点精度的原因,它实际上可能是
0.999999
1.0000001

相反,你通常更倾向于对照某个范围进行检查,例如

if(Mathf.Abs(a - b) <= someThreshold)
private readonly float Speed = 1.5f;

private Vector2 target;
private Vector2 start;
private float timePassed;
private float duration;

public override void OnStart()
{
   target = new Vector2(Random.Range(0.1f, 0.5f), transform.position.y);
   start = transform.position;

   duration = Vector2.Distance(start, target) / speed;
   timePassed = 0f;
}

public override TaskStatus OnUpdate()
{
    if (timePassed >= duration)
    {
        transform.position = target;
        return TaskStatus.Success;
    }

    var factor = timePassed / duration;

    //MAGIC

    transform.position = Vector2.Lerp(start, target, factor);

   timePassed += Time.deltaTime;
    
   return TaskStatus.Running;
}
factor = Mathf.SmoothStep(0, 1, factor);
基本上等于使用

if(Mathf.Abs(a - b) <= Mathf.Epsilon)
到目前为止,这将是一个与以前一样的线性运动;)

因此,让我们来填写
魔术

一个非常简单的易入易出选项是使用like,例如

if(Mathf.Abs(a - b) <= someThreshold)
private readonly float Speed = 1.5f;

private Vector2 target;
private Vector2 start;
private float timePassed;
private float duration;

public override void OnStart()
{
   target = new Vector2(Random.Range(0.1f, 0.5f), transform.position.y);
   start = transform.position;

   duration = Vector2.Distance(start, target) / speed;
   timePassed = 0f;
}

public override TaskStatus OnUpdate()
{
    if (timePassed >= duration)
    {
        transform.position = target;
        return TaskStatus.Success;
    }

    var factor = timePassed / duration;

    //MAGIC

    transform.position = Vector2.Lerp(start, target, factor);

   timePassed += Time.deltaTime;
    
   return TaskStatus.Running;
}
factor = Mathf.SmoothStep(0, 1, factor);
或者你现在可以用

factor = yourAnimationCurve.Evaluate(factor);

这使您可以完全控制移动的平滑度,但会产生
速度的总平均速度
,就好像您会线性应用它一样。

您可以发布当前代码吗?到目前为止,你到底是如何移动这些对象的?当然,我已经在我的帖子中添加了代码。你至少可以轻松地查看一下。。然而,使用您当前的方法,很难准确地判断何时应该开始一个新的运动…因此我尝试了这种方法来计算何时应该开始轻松进入/退出,但它没有正常工作:
private float GenerateTimeToReachDestination(){float Distance=Vector2.Distance(transform.position,BugDirection.Value);返回距离/速度;}
在更新中,我有这样的逻辑:
CurrentTime+=Time.deltaTime;float CurrentSpeed=AnimationMovementCurve.Evaluate(CurrentTime/TimeToReachDestination)不起作用,甚至不接近,即使我把逻辑拉到一个协同程序中。(对奇怪的格式表示抱歉)如前所述,主要问题是:你如何确切地知道一个新动作何时开始,何时结束?
BugDirection
是否持续更改?谢谢您的详细回答!我将研究重构我的代码,并删除了有问题的浮点比较。