Mathf.Lerp缺少最终值

时间:2018-11-19 20:53:21

标签: unity3d math lerp

我正在使用Mathf.Lerp为圆形进度栏设置动画。

进度条是具有名为“ FillAmount”的属性的图像:

0 means not filled
1 means filled

连同Fill属性“ Radial 360”一样,它的作用有点像时钟。

由于某种原因,错过了执行Lerp函数后的最终值,我看不出如何改进该函数以达到预期的结果。

我的圆形进度条是3/4圈,这就是为什么我将uFrom和uTo(介于0和100之间)乘以0.75的原因。

这是我的代码:

public IEnumerator AnimateHealthChange(int uFrom, int uTo)
{
    float fFade = 0.25f;

    float fOld = ((uFrom * 0.75f) / 100);
    float fNew = ((uTo * 0.75f) / 100);

    Debug.Log("Changing from " + fOld.ToString() + " to " + fNew.ToString());

    for (float t = 0.01f; t < fFade; t += Time.deltaTime)
    {
        ImageHealthRing.fillAmount = Mathf.Lerp(fOld, fNew, Mathf.Min(1, t / fFade));
        yield return null;//
    }

    Debug.Log("Final filling after for-next-statement: " + ImageHealthRing.fillAmount.ToString());

    yield return null;
}

例如,当我调用AnimateHealthChange(0,100)时,得到以下日志输出:

Changing from 0 to 0.75

Final filling after for-next-statement: 0.6807814

我希望最终结果为0.75,而不是0.6807814。

有人看到我的错误,还是我错误地使用了Lerp?

enter image description here

3 个答案:

答案 0 :(得分:2)

您的for循环是一个问题,因为它无法保证:

for (float t = 0.01f; t < fFade; t += Time.deltaTime)

Time.deltaTime可以是任意数字(取决于游戏的性能和帧速率),并且您使用的是t < fFade而不是t <= fFade,因此即使您偶然这样做,以t == fFade结尾(这是应该正确填充的值),它将跳过循环的迭代。

最简单的解决方案是在循环后添加一个额外的语句,将fillAmount强制设置为适当的值:

    ...
    yield return null;//
}
ImageHealthRing.fillAmount = fNew;

这样,您的循环仍然可以处理动画,并且当函数结束时,可以保证动画以正确的值结束。

答案 1 :(得分:2)

可能在for循环中。查看其执行方式: 最初,t设置为0.01。 Healthbar有所更改。 然后,t增加Time.deltaTime。例如,它恰好是0.17。现在t等于0.18,循环继续运行。

但是,当另一个增量t大于或等于fFade时,程序将退出循环,而不会更改运行状况栏。在我的示例中,最后处理的号码为0.18

该如何解决?您应在循环后立即将fillAmount设置为fNew。

答案 2 :(得分:0)

代替使用for循环。使用while循环。因此您的代码将运行直到达到所需的值。

现在,您要根据时间而不是根据期望的结果退出。 您仍然可以按时间运行每个帧并设置动画,但是您不应该根据其运行时间来停止代码。

此外,退出循环时,还应该钳位/设置值。将其设置为您在函数中输入的参数(或fNew)。