Mathf.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?

3 ответа

Решение

Ваш 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 Новое сразу после цикла.

Вместо использования for петля. Использовать while петля. поэтому ваш код работает, пока не достигнет желаемого значения.

Прямо сейчас вы выходите, основываясь на времени, а не на желаемом результате. Вы по-прежнему можете запускать каждый кадр и анимировать по времени, но не следует останавливать код на основе времени его выполнения.

Кроме того, может также стоить зафиксировать / установить значение при выходе из цикла. Либо установите его на параметр, который вы ввели в функцию (или fNew в твоем случае).

Другие вопросы по тегам