Разница между методом обновления и FixedUpdate в Unity?

14

Я начинаю изучать Unity3d, и одна из путаниц, которые я получаю, это разница между Update()и FixedUpdate().

Я следую там руководству по разработке игр для Lynda Unity 2D, инструктор использует Updateметод, у игрока есть компонент RigidBody2D и Box collider, он использует Updateметод для перевода игрока, но когда я делаю то же Updateсамое, игрок не двигается, а когда я делаю это FixedUpdateвсе работает. Он дает уроки по Unity 4.3, а я беру курс по Unity 4.6.

Где я должен использовать Updateи FixedUpdate?

монах
источник

Ответы:

14

Я собирался написать это как комментарий, но это оказалось довольно длинным, поэтому я превратил это в ответ.

Текущие ответы в основном правильные, но несколько упомянутых вещей вводят в заблуждение / неправильно.

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

Например, вы не хотите опрашивать входные данные FixedUpdate(не из-за производительности, а потому, что вызовы просто не будут работать правильно). ИИ падает в одну лодку.

Постоянно обновляемая физика - единственное задание, связанное с геймплеем, которое FixedUpdateнужно использовать. Непрерывные / разовые вызовы таких вещей, как Physics.Raycastили даже Rigidbody.AddForceпринадлежат Update. Мое упоминание оRigidbody.AddForce , казалось бы, противоречит тому, что может подразумеваться в документации, но ключ непрерывный против непрерывного.

Одна огромная причина, по которой принадлежит только непрерывная физика, FixedUpdate- это фактическая природа FixedUpdate. В других ответах упоминалось, как FixedUpdate вызывается в фиксированном interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime/ Time.fixedDeltaTime*, который не соответствует непосредственно фактическому времени между вызовами, а скорее моделируемому времени между вызовами.

(* Time.deltaTimeи Time.fixedDeltaTimeимеют одинаковое значение при вызове в FixedUpdate[Unity может определить, произошел ли текущий вызов и Time.deltaTimeво время FixedUpdateвозврата Time.fixedDeltaTime))

Естественно, один и тот же способ Updateне может быть вызван постоянным образом из-за разной производительности FixedUpdate. Основное отличие состоит в том, что каждый кадр, если FixedUpdateего не вызывали достаточно часто для усреднения до правильного интервала между вызовами, он вызывается несколько раз (или не вызывается, слишком высокое среднее значение). Это то, на что ссылаются документы по порядку выполнения, говоря, что FixedUpdate может вызываться несколько раз за кадр:

... FixedUpdate: FixedUpdate часто вызывается чаще, чем Update. Его можно вызывать несколько раз за кадр, если частота кадров низкая, и его вообще нельзя вызывать между кадрами, если частота кадров высокая ...

Это не влияет на физику из-за характера остальной части порядка выполнения и движка, но почти все, что вы вставляете в FixedUpdate будет затронуто добавите, и это вызовет проблемы.

Например, если вы поместите обработку AI внутри FixedUpdate нет никаких оснований предполагать, что ИИ не будет пропускать обновления для нескольких кадров подряд. Кроме того, каждый раз, когда `FixedUpdate отстает, ваш ИИ будет обновляться несколько раз в одном кадре до того, как будут обрабатываться такие вещи, как физика и ввод / движение игрока, что, по крайней мере, является пустой тратой обработки, но также весьма вероятно, что вызовет сложный процесс. чтобы отследить ошибки и неустойчивое поведение.

Если вам нужно что-то делать с фиксированным интервалом, используйте другие методы, которые предоставляет Unity, такие как CoroutinesиInvokeRepeating .

И небольшая заметка о Time.deltaTime когда и как его использовать:

Самый простой способ описать эффект Time.deltaTime - это изменение числа от единицы на кадр до единицы в секунду . Например, если у вас есть скрипт с чем-то вроде transform.Translate(Vector3.up * 5)Update, вы по существу перемещаете преобразование со скоростью 5 метров на кадр . Это означает, что если частота кадров низкая, движение будет медленнее, а если частота кадров высокая, движение будет быстрее.

Если вы возьмете тот же код и измените его на transform.Translate(Vector3.up * 5 * Time.deltaTime), объект будет перемещаться со скоростью 5 метров в секунду . Это означает, что независимо от частоты кадров, объект будет перемещаться на 5 метров каждую секунду (но чем медленнее частота кадров, тем выше будет движение объекта, так как он все равно перемещается на одну и ту же величину каждые X секунд)

В общем, вы хотите, чтобы ваше движение было в секунду. Таким образом, независимо от скорости компьютера, ваша физика / движение будет вести себя одинаково, и у вас не будет странных ошибок, появляющихся на медленных устройствах.

И нет смысла использовать его в FixedUpdate. Из-за того, что я упомянул выше, вы будете получать одно и то же значение при каждом вызове (значение «Фиксированное время обновления»), и оно ничего не изменит с вашими значениями. Движение / физика, определенные в FixedUpdate, уже будут в единицах в секунду, поэтому вам это не нужно.

Селали Адобор
источник
4

UpdateФункция вызывается каждый кадр. Его частота зависит от того, насколько быстро компьютер способен отображать изображения. На более медленном компьютере Updateвызывается реже, чем на более быстром. Если вы выполняете расчеты на основе времени, вы можете нормализовать их, используя информацию о Time.deltaTimeтом, сколько времени прошло с момента последнего Updateвызова (применяются предостережения).
Вы будете обычно использоватьUpdate для выполнения задач, связанных с отображением (например, обновление элемента пользовательского интерфейса)

FixedUpdateФункция вызывается через определенные промежутки времени. Независимо от того, как часто изображение обновляется, FixedUpdateего будут вызывать 1/Time.fixedDeltaTimeраз в секунду.
Обычно вы будете использовать его FixedUpdateдля выполнения задач, связанных с игровым процессом (например, обновление физики).

3Doubloons
источник
Является ли это альтернативой умножению на время Time.delta? Есть ли причина использовать один или другой?
Бен
@ У них две разные цели, и вы должны использовать правильную функцию для того, что вы делаете.
о0 '.
@Lohoris Извините, я имел в виду, есть ли причина использовать FixedUpdate поверх Update и умножать вещи на Time.deltaTime, чтобы сделать их независимыми от кадров?
Бен
@ Да, точность. В системе с медленным рендерингом, Updateвызывается все реже и реже, и ваша симуляция сильно пострадает от этого. Вы можете не заметить, пока симуляция проста, но она легко сломается, когда это не так.
о0 '.
1
@Ben no: если вы хотите, чтобы ваша симуляция была точной, вы должны делать много маленьких шагов, а не огромных, случайным образом увеличивающихся или уменьшающихся каждый раз. И нет, весь смысл FixedUpdate в том, что он вызывается так много раз, без вопросов.
о0 '.
2

От: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate

Шаг по времени, используемый в FixedUpdate, не является переменным.

Если ваша игра начинает зависать, когда она догоняет, вам не нужно> 10 секунд физики в одном обновлении, поэтому обычно это делается в FixedUpdate, который вызывается с фиксированным интервалом.

Например:

Update(float elapsedSeconds)
{
  Position += Velocity * 34.23423; //Windows Update is self-important
}
FixedUpdate(float elapsedSeconds)
{
  Position += Velocity * 0.0166; //60fps
}

Где:

Update(34.23423)

==

FixedUpdate(10.0)
FixedUpdate(10.0)
FixedUpdate(10.0)
//4.23423 + 5.76577 game-seconds later...
FixedUpdate(10.0)
Джон
источник
Я упоминал об этом в своем ответе, но на FixedUpdateсамом деле не вызывается с фиксированным интервалом. Фактическая сущность FixedUpdateсостоит в том, чтобы сжать несколько циклов физики в один кадр, если ваша игра начинает отставать, и пропустить циклы, если она идет слишком быстро, так что среднее значение подходит к Фиксированному временному шагу обновления. Unity не является многопоточным, поэтому невозможно было бы гарантировать вызовы FixedUpdate с фиксированным интервалом (что происходит, когда один FixedUpdate занимает слишком много времени). Даже если бы это было так, вероятно, все равно было бы почти невозможно.
Селали Адобор
Большинство [Unity?] Людей не знают, что Render / Update / FixedUpdate все вызываются из одного метода обратного вызова, поэтому я концептуализировал. Спасибо за ваши усилия!
Джон
2

Updateназывается как можно быстрее. Переменная Time.deltaTime устанавливается на фактическое количество времени, прошедшее с момента последнего вызова. Если задержка или что-то подобное замедляет игру, Updateона все равно будет вызвана только один раз, когда задержка закончится, с высоким значением deltaTime.

FixedUpdateвызывается через равные промежутки времени. Он никогда не будет вызываться чаще, чем соотношение, указанное в Time.fixedDeltaTime. Если задержка или что-то подобное замедляет игру, FixedUpdateона будет вызываться несколько раз подряд, чтобы игра могла наверстать упущенное. Time.deltaTimeустанавливается равным, Time.fixedDeltaTimeпрежде чем FixedUpdateвыполняется, но это просто выдумка, чтобы облегчить перенос кода между ними.

Как правило, Updateследует использовать для интерполируемого поведения и FixedUpdateдля поведения, которое должно вычисляться поэтапно или зависеть от того, что делает, например, движения, основанного на физике. Если вы пишете какой-либо цикл Updateвдоль строк, for(time=0;time<=deltaTime;time+=someStep)...то вам, вероятно, следует делать это в FixedUpdate.

Марк Грин
источник