Mathf.Lerp 未达到最终值

Mathf.Lerp misses final value

我正在使用 Mathf.Lerp 制作圆形进度条的动画。

进度条是一个有 属性 名为 "FillAmount" 的图像:

0 means not filled
1 means filled

与填充 属性 "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?

你的 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;

这样你的循环仍在处理动画,当你的函数结束时,你保证它以正确的值结束。

可能在 for 循环中。看看它是如何执行的: 最初,t 设置为 0.01。 Healthbar改变了一点。 然后,t 增加 Time.deltaTime。比如刚好是0.17。现在 t 等于 0.18 并且循环继续到 运行.

但是当另一个增量 t 变得大于或等于 fFade 时,程序将退出循环 而不会更改健康栏 。在我的示例中,最后处理的数字将是 0.18.

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

而不是使用 for 循环。使用 while 循环。所以你的代码 运行s 直到达到所需的值。

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

此外,当您退出循环时,它也可能值 clamping/setting 值。将其设置为您在函数中输入的参数(或 fNew 在您的情况下)。