Анимация движения на разные расстояния
Задача: сделать анимацию перемещения объекта из одной точки в другую. При этом расстояние между точками может быть разное, как очень маленькое, так и очень большое.
Пример 1: Сделать перемещение аватара персонажа по карте между ключевыми точками.
Пример 2: Сделать анимацию смещения полоски прогресса. В этом случае, мы хотим сделать анимацию достаточно долгой, чтобы игрок успел обратить на нее внимание.
Пример 3: Сделать пролистывание списка от элемента X до элемента Y.
Как правило, такие анимации делаются через твины (tweens). Это значит, что указываются координаты начальной и конечной точки, время, отводимое на перемещение, и функция плавности.
Обычно мы ожидаем нелинейный характер передвижения: Мы хотим, чтобы объект разгонялся в начале и притормаживал в конце.
Время
Обычно в настройки выносится время, которое будет отводиться на такую анимацию.
Этот вариант может не нравиться тем, что на больших расстояниях объект будет двигаться слишком быстро. А если увеличить время, то на маленьких расстояниях — слишком медленно. Придется искать компромисс.
Впрочем, такой логики иногда достаточно.
Cредняя скорость
Можно вынести не само время, а зависимость времени от расстояния — среднюю скорость на перемещение (Movement AvgSpeed). И соответственно высчитывать время на анимацию, как:
Time = Distance / MovementAvgSpeed;
Но, настроив приемлемую скорость для одного из случаев, мы получим плохой результат на другом расстоянии. Например, на маленьком расстоянии объект будет слишком быстро перескакивать к новой точке.
Временные рамки
Попробуем выразить разговорным языком, что же нам нужно в идеале: «Надо, чтобы объект двигался от 2 до 5 секунд в зависимости от того, насколько далеко ему нужно проехать».
То есть, по сути, нам подходит использование средней скорости, но нужно еще наложить ограничения на получаемое время. Ввести MinTime и MaxTime — минимальное и максимальное время на перемещение.
Итого, у нас получается три параметра для анимации:
// Рассчитанное время будет >= MinTime, но <= MaxTime Time = Mathf.Clamp(Distance / MovementAvgSpeed, MinTime, MaxTime);
Если выразить полученную функцию графиком: