Изменения во времени обработки
При заданной частоте кадров в кадрах в секунду (FPS) продолжительность отдельных кадров, как правило, меняется. Эти изменения могут быть незначительными. Например, в игре, работающей на частоте 60 FPS, фактическое количество кадров в секунду может незначительно меняться, так что каждый кадр длится от 0.016 до 0.018 секунд. Большие изменения могут произойти, когда ваше приложение выполняет тяжелые вычисления или сбор мусора, или когда существует конкуренция за ресурсы с другими приложениями.
Регистрация прошедшего времени
Time.time указывает время, прошедшее с момента запуска приложения, и поэтому обычно увеличивается непрерывно и устойчиво. Time.deltaTime указывает время, прошедшее с момента последнего кадра, и поэтому в идеале остается достаточно постоянным. Оба эти значения основаны на в игре, а не в реальном времени, что означает, что они учитывают любое масштабирование времени, которое вы применяете. Например, если вы установите Time.timeScale на 0.1 для эффекта замедления, значение Time.time увеличивается на 10% скорости реального времени. После 10 секунд реального времени значение Time.time увеличилось бы на 1.
В дополнение к замедлению или ускорению времени в вашей игре, вы можете установить Time.timeScale на нуль, чтобы приостановить вашу игру. В этом случае Unity все еще вызывает метод Update, но Time.time вообще не увеличивается, а Time.deltaTime равен нулю.
Ограничение отклонений от зарегистрированного времени
Эти значения также ограничены значением Time.maximumDeltaTime. Длина любых пауз или изменений частоты кадров, сообщаемых этими свойствами, никогда не превысит Time.maximumDeltaTime. Например, если происходит задержка в одну секунду, но maximumDeltaTime установлено на значение по умолчанию 0.333, Time.time увеличивается только на 0.333, а Time.deltaTime равен 0.333, несмотря на то, что в реальном мире проходит одна секунда.
Немасштабированные версии каждого из этих свойств (Time.unscaledTime и Time.unscaledDeltaTime) игнорируют эти ограничения и отображают фактическое время, прошедшее в обоих случаях. Это полезно для всего, что должно реагировать с фиксированной скоростью, даже когда игра играет в замедленном режиме. Примером этого является анимация взаимодействия UI.
В таблице ниже показан пример 16 кадров, проходящих один за другим, с одной большой задержкой в середине, на одном кадре. Эти цифры иллюстрируют, как различные Time класса сообщают о таком сильном разбросе частоты кадров и реагируют на него.
| Рамка | unscaledTime | время | unscaledDeltaTime | deltaTime | smoothDeltaTime |
|---|---|---|---|---|---|
| 1 | 0.000 | 0.000 | 0.018 | 0.018 | 0.018 |
| 2 | 0.018 | 0.018 | 0.018 | 0.018 | 0.018 |
| 3 | 0.036 | 0.036 | 0.018 | 0.018 | 0.018 |
| 4 | 0.054 | 0.054 | 0.018 | 0.018 | 0.018 |
| 5 | 0.071 | 0.071 | 0.017 | 0.017 | 0.018 |
| 6 | 0.089 | 0.089 | 0.018 | 0.018 | 0.018 |
| 7 | 0.107 | 0.107 | 0.018 | 0.018 | 0.018 |
| 8 (и) | 1.123 (и) | 0.440 (с) | 1.016 (и) | 0.333 (и) | 0.081 (и) |
| 9 | 1.140 | 0.457 | 0.017 | 0.017 | 0.066 |
| 10 | 1.157 | 0.474 | 0.017 | 0.017 | 0.056 |
| 11 | 1.175 | 0.492 | 0.018 | 0.018 | 0.049 |
| 12 | 1.193 | 0.510 | 0.018 | 0.018 | 0.042 |
| 13 | 1.211 | 0.528 | 0.018 | 0.018 | 0.038 |
| 14 | 1.229 | 0.546 | 0.018 | 0.018 | 0.034 |
| 15 | 1.247 | 0.564 | 0.018 | 0.018 | 0.031 |
| 16 | 1.265 | 0.582 | 0.018 | 0.018 | 0.028 |
Кадры с 1 по 7 работают с постоянной скоростью приблизительно 60 кадров в секунду. Обратите внимание, что Time.time и Time.unscaledTime постоянно увеличиваются вместе, указывая на то, что Time.timeScale установлен на 1.
На кадре 8 (и) возникает большая задержка чуть больше одной секунды. Это может быть вызвано конкуренцией за ресурсы. Например, когда операция блокирует основной процесс, пока он загружает большое количество данных с диска.
Когда задержка кадра превышает Time.maximumDeltaTime, Unity ограничивает значение, сообщаемое Time.deltaTime, и количество, добавляемое к Time.time. Это позволяет избежать нежелательных побочных эффектов, которые могут возникнуть, если шаг времени превышает это количество. Без ограничения объекты, движение которых масштабируется Time.deltaTime, могут теоретически перемещаться на неограниченные расстояния от одного кадра к следующему. Это может вызвать эффект глитча, когда, например, персонажи беспрепятственно проходят через препятствия, такие как стены.
Вы можете настроить Time.maximumDeltaTime в Редакторе, изменив настройку Максимально допустимый шаг времени в окне Время или в коде, установив значение свойства Time.maximumDeltaTime.
Значение по умолчанию Time.maximumDeltaTime равняется одной трети секунды (0.3333333). Это означает, что в игре, где движение контролируется Time.deltaTime, движение объекта от одного кадра к следующему ограничивается расстоянием, которое он может пройти за одну треть секунды, независимо от того, сколько времени фактически прошло с предыдущего кадра.
Рассмотрение данных из предыдущей таблицы в графической форме может помочь визуализировать, как эти временные свойства ведут себя по отношению друг к другу:
На кадре 8, Time.unscaledDeltaTime (d) и Time.deltaTime (e) различаются в том, сколько времени они сообщают, что прошло. Хотя целая секунда реального времени прошла между кадрами 7 и 8, Time.deltaTime сообщает только 0.333 секунд. Это потому, что Time.deltaTime ограничено значением Time.maximumDeltaTime.
Аналогичным образом, Time.unscaledTime (b) увеличилось примерно на целую секунду, потому что было добавлено истинное (неограниченное) значение, в то время как Time.time (c) увеличилось только на меньшее ограниченное значение. Time.time не настигает прошедшее реальное время, и вместо этого ведет себя так, как будто задержка была только Time.maximumDeltaTime по продолжительности.
Свойство Time.smoothDeltaTime сообщает приближение последних значений Time.deltaTime со всеми изменениями, сглаженными в соответствии с алгоритмом. Это еще один способ избежать нежелательных колебаний в движении или других расчетах, основанных на времени. В частности, те, которые падают ниже порогового значения, установленного Time.maximumDeltaTime. Алгоритм сглаживания не может предсказать будущие изменения, но он постепенно адаптирует свое сообщаемое значение для сглаживания изменений в недавно прошедших значениях Time.deltaTime, так что среднее сообщаемое время остается приблизительно эквивалентным фактическому прошедшему времени.
Временная вариация и фиксированный цикл обновления
Значение maximumDeltaTime также влияет на цикл фиксированного обновления. Физическая система использует фиксированный интервал времени, определенный Time.fixedDeltaTime, чтобы определить, сколько времени потребуется для имитации на каждом шаге. Unity пытается держать физическую симуляцию в соответствии с прошедшим временем и иногда выполняет несколько обновлений физики на кадр.
Однако, если физическая симуляция слишком сильно отстает, физической системе может потребоваться большое количество шагов, чтобы догнать текущее время. Эти шаги догнать могут сами по себе вызвать дополнительное замедление. Чтобы избежать обратной связи замедлений, значение Time.maximumDeltaTime также действует как ограничение времени, которое физическая система симулирует между любыми двумя заданными кадрами.
Если обновление кадра занимает больше времени, чем Time.maximumDeltaTime, движок физики не пытается симулировать дополнительное время, а вместо этого позволяет обработке кадра наверстать упущенное. После завершения обновления кадра физика возобновляется так, как будто с момента остановки не прошло времени.
Результатом этого является то, что физические объекты не будут двигаться идеально в реальном времени, как они обычно делают, но будут немного замедляться. Тем не менее, система физики все еще отслеживает их, как если бы они двигались нормально. Замедление физического времени обычно не заметно и часто является приемлемым компромиссом с производительностью игры.
Логика времени Unity
Следующая блок-схема иллюстрирует логику, которую Unity использует для подсчета времени в одном кадре, и как свойства time, deltaTime, fixedDeltaTimeи maximumDeltaTime связаны друг с другом.