Vector3.Lerp внутри сопрограммы не работает должным образом в Unity3D

#c# #unity3d #coroutine #ienumerator

#c# #unity3d #сопрограмма #ienumerator

Вопрос:

У меня странная проблема при использовании a Vector3.Lerp внутри сопрограммы, и это не имеет смысла, потому что в моей игре много сопрограмм, и все они работают нормально.

ЧЕГО Я ПЫТАЮСЬ ДОСТИЧЬ

Я просто пытаюсь переместить объект с начальной высоты на конечную высоту с помощью вызываемой сопрограммы InVolo() и простого Vector3.Lerp изменения положения объекта.

МОЙ КОД

 float elapsedTime = 0f;

    while (elapsedTime < TempoSalita)
    {


        transform.position = Vector3.Lerp(transform.position, 
            new Vector3(transform.position.x, maxHight, transform.position.z), (elapsedTime / TempoSalita));


        elapsedTime  = Time.deltaTime;

        yield return null;
    }

    transform.position = new Vector3(transform.position.x, maxHight, transform.position.z);
    yield return null;
 

Это maxHight просто 4f и TempoSalita 2f . Сопрограмма запускается в OnTriggerEnter и работает нормально, объект достигает y 4f и завершает работу через 2 секунды.

ПРОБЛЕМА

В принципе, elapsedTime / TempoSalita становится 1 через 2 секунды, как и должно быть, но объект достигает конечной позиции примерно через 0,3 секунды, когда elapsed/TempoSalita это 0,2, и для меня это не имеет смысла. Vector3.Lerp должен переходить от startpos к endpos за время, пока значение t изменяется с 0 на 1. Но он переходит в конечную позицию через 0,2 секунды, и я понятия не имею, почему.

ЧТО я ПРОБОВАЛ

Я попытался Debug.Log использовать прошедшее время, и оно меняется нормально, пытался использовать только Mathf.Lerp между значениями y, и это делает то же самое. В этом скрипте больше нет ничего, что могло бы повлиять на это, так запускается сопрограмма:

  void OnTriggerEnter(Collider other)
{
    if(other.CompareTag("Saltino"))
    {
        StartCoroutine(InVolo());
        
    }
}
 

Он запускается только один раз. Знаете ли вы, что может вызвать эту странную проблему?

Комментарии:

1. Vector3.Lerp should go from startpos to endpos да, но вы всегда используете текущую позицию как startpos => вы интерполируете из уже продвинутой позиции, а остальная часть «анимации» просто движется очень медленно, поскольку начальная и конечная позиции сближаются

Ответ №1:

Это может быть условие, которое вы используете, которое кажется мне немного подозрительным.

Обычно я бы написал это немного по-другому, что-то вроде..

 var t = 0f;
var start = transform.position;
var target = new Vector3(transform.position.x, maxHight, transform.position.z);

while (t < 1)
{
    t  = Time.deltaTime / TempoSalita;

    if (t > 1) t = 1;

    transform.position = Vector3.Lerp(start, target, t);

    yield return null;
}
 

Сначала вы создаете свои начальные и целевые значения, прежде чем изменять позицию. Значение t будет увеличиваться до тех пор, пока не достигнет (или не пройдет) 1. Поскольку мы не хотим, чтобы t превышало 1, мы выполняем проверку перед применением lerp. Наше значение t вычисляется вне lerp, чтобы сделать его понятным и простым для чтения / изменения.

Вышеуказанное будет выполняться в течение указанного времени и не требует дополнительных строк в конце, поскольку t в конечном итоге будет ровно 1.

Комментарии:

1. Я не уверен, почему это работает, но, БОЖЕ, это работает, спасибо!

2. @Leoverload чтобы узнать больше о lerp и о том, как работает этот код, вы можете обратиться к этой замечательной статье: chicounity3d.wordpress.com/2014/05/23/how-to-lerp-like-a-pro

3. @Leoverload Прошу прощения; Я действительно не знаю.

4. Проблема вовсе не в условии, а в том, что OP всегда использует текущую позицию в качестве начального значения для Lerp => Начальная и конечная позиции с каждым разом становятся ближе друг к другу => в остальной части цикла объект просто перемещается очень маленькими шагами

5. Понял, спасибо, Дарт @derHugo мудрый: D