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


14

я починаю вивчати Unity3d, і одне з непорозумінь, які я отримую, - це різниця між Update()та FixedUpdate().

Я Updateслідкую за підручником з розробки гри Lynda Unity 2D там, інструктор використовує метод, у гравця є компонент RigidBody2D і колайдер Box, він використовує Updateметод для перекладу гравця, але коли я це роблю в Updateпрогравачі, не рухається, але коли я роблю це в FixedUpdate, все працює. Він дає підручник з Unity 4.3, і я проходжу курс в Unity 4.6.

Де я повинен використовувати Updateі FixedUpdate?

Відповіді:


14

Я збирався написати це як коментар, але в кінцевому підсумку це було досить довго, тому я перетворив це на відповідь.

Поточні відповіді здебільшого вірні, але кілька згаданих речей є оманливими / неправильними.

В цілому, більшість завдань , пов'язаних з грою-ігри будуть йти Update.

Наприклад, ви не хочете проводити опитування для введення даних FixedUpdate(не через продуктивність, а тому, що дзвінки просто не працюватимуть правильно). AI падає в одному човні.

Постійно оновлювана фізика - це єдине завдання, пов'язане з геймплеєм, для якого 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його не викликають достатньо часто, щоб перерахувати правильний інтервал між дзвінками, він називається багаторазово (або не називається середній занадто високий). Це те, на що посилаються документи в Order Execution, говорячи про те, що FixedUpdate можна викликати кілька разів кадром:

... FixedUpdate: FixedUpdate часто називають частіше, ніж Оновити. Його можна назвати кілька разів на кадр, якщо частота кадрів низька і взагалі не може бути викликана між кадрами, якщо частота кадрів висока ...

Це не впливає на фізику через характер решти наказу про виконання та двигун, але майже все, що ви введете, FixedUpdateбуде зачеплене, і це спричинить проблеми.

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

Якщо вам потрібно щось робити через фіксований інтервал, використовуйте інші методи Unity, такі як Coroutinesі InvokeRepeating.

І невелика примітка про те, Time.deltaTimeі коли його використовувати:

Найпростіший спосіб описати ефект Time.deltaTime - це зміна числа від одиниці на кадр до одиниці в секунду . Наприклад, якщо у вас є сценарій з чимось на зразок transform.Translate(Vector3.up * 5)оновлення, ви по суті рухаєте перетворення зі швидкістю 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для виконання завдань, пов’язаних з ігровими процесами (наприклад, оновлення фізики)


Чи це альтернатива множення на час Time.delta? Чи є причина використовувати те чи інше?
Бен

@ У них дві різні цілі, і ви повинні використовувати правильну функцію для того, що ви робите.
o0 '.

@Lohoris Вибачте, я мав на увазі, чи є причина використовувати FixedUpdate над оновленням та множенням речей на Time.deltaTime, щоб зробити їх кадрами незалежними?
Бен

@Ben так, точність. У системі з повільною візуалізацією Updateвсе рідше дзвонять, і ваше моделювання буде сильно страждати від цього. Ви можете не помітити, поки симуляція проста, але вона легко жахливо зламається, коли її немає.
o0 '.

1
@Ben no: якщо ви хочете, щоб ваше моделювання було точним, вам доведеться робити багато маленьких кроків, а не величезних випадково більших чи менших щоразу. І ні, вся суть FixedUpdate полягає в тому, що йому дзвонять так багато разів, без запитань.
o0 '.

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 займає занадто багато часу). Навіть якщо б це було, це, мабуть, все ще було б майже неможливо.
Selali Adobor

Більшість людей [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 замість цього.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.