Chciałem napisać to jako komentarz, ale skończyło się to dość długim rozwiązywaniem, więc przekształciłem to w odpowiedź.
Obecne odpowiedzi są w większości poprawne, ale kilka wspomnianych rzeczy jest mylących / błędnych.
Ogólnie rzecz biorąc, większość zadań związanych z grą zostanie wykonana Update
.
Na przykład nie chcesz odpytywać danych wejściowych FixedUpdate
(nie ze względu na wydajność, ale ponieważ wywołania po prostu nie będą działać poprawnie). AI wpada do tej samej łodzi.
Ciągle aktualizowana fizyka to jedyne zadanie związane z rozgrywką, do którego FixedUpdate
należy się zastosować. Nieciągłe / raz na jakiś czas połączenia do takich rzeczy Physics.Raycast
, a nawet do nich Rigidbody.AddForce
należą Update
. Moja wzmianka o Rigidbody.AddForce
pozornie jest sprzeczna z tym, co może wynikać z dokumentacji, ale kluczem jest ciągły kontra nieciągły.
Jednym z ogromnych powodów, dla których należą tylko ciągła fizyka, FixedUpdate
jest faktyczna natura FixedUpdate
. W innych odpowiedziach wspomniano, w jaki sposób FixedUpdate jest wywoływany jako fixed interval, but that's slightly misleading. In reality, a script is passed a time in Time.deltaTime
/ Time.fixedDeltaTime
*, który nie odpowiada bezpośrednio faktycznemu czasowi między rozmowami, ale raczej symulowanemu czasowi między rozmowami.
(* Time.deltaTime
i Time.fixedDeltaTime
mają tę samą wartość, gdy są wywoływane w FixedUpdate
[Unity jest w stanie stwierdzić, czy bieżące wywołanie zostało nawiązane Time.deltaTime
podczas FixedUpdate
i zwraca Time.fixedDeltaTime
])
Oczywiście tego samego sposobu Update
nie można wywoływać w sposób ciągły ze względu na różną wydajność, nie można tego zrobić FixedUpdate
. Kluczową różnicą jest to, że każda ramka, jeśli FixedUpdate
nie była wywoływana wystarczająco często, aby uśrednić prawidłowy odstęp między połączeniami, jest wywoływana wiele razy (lub nie jest nazywana średnia jest zbyt wysoka). Oto do czego odnoszą się dokumenty dotyczące polecenia wykonania, mówiąc, że FixedUpdate można wywoływać wiele razy ramkę:
... FixedUpdate: FixedUpdate jest często nazywany częściej niż Aktualizacja. Może być wywoływany wiele razy na klatkę, jeśli częstotliwość klatek jest niska i może nie być w ogóle wywoływana między klatkami, jeśli częstotliwość klatek jest wysoka ...
Nie wpływa to na fizykę ze względu na naturę pozostałej kolejności wykonania i silnika, ale FixedUpdate
wpłynie to na wszystko, co włożysz , i spowoduje problemy.
Na przykład, jeśli umieścisz w nim przetwarzanie AI, FixedUpdate
nie ma powodu, aby zakładać, że AI nie pominie aktualizacji wielu ramek z rzędu. Dodatkowo, za każdym razem, gdy `FixedUpdate pozostaje w tyle, twoja sztuczna inteligencja aktualizuje się wiele razy w jednej klatce, zanim zostaną przetworzone takie rzeczy jak fizyka i wejście / ruch gracza, co jest co najmniej marnotrawstwem przetwarzania, ale jest również bardzo prawdopodobne, że spowoduje trudne aby wyśledzić błędy i nieprawidłowe zachowanie.
Jeśli chcesz coś zrobić w ustalonym odstępie czasu, użyj innych metod, które zapewnia Unity, takich jak Coroutines
i InvokeRepeating
.
I mała uwaga na temat Time.deltaTime
i kiedy go używać:
Najłatwiejszym sposobem opisania efektu Time.deltaTime jest zmiana liczby z jednostki na ramkę na jednostkę na sekundę . Na przykład, jeśli masz skrypt z czymś takim jak transform.Translate(Vector3.up * 5)
w aktualizacji, zasadniczo przesuwasz transformację z prędkością 5 metrów na klatkę . Oznacza to, że jeśli liczba klatek na sekundę jest niska, ruch jest wolniejszy, a jeśli liczba klatek na sekundę jest wysoka, ruch jest szybszy.
Jeśli weźmiesz ten sam kod i zmienisz na transform.Translate(Vector3.up * 5 * Time.deltaTime)
, obiekt będzie przemieszczany z prędkością 5 metrów na sekundę . Oznacza to, że bez względu na liczbę klatek na sekundę obiekt porusza się o 5 metrów co sekundę (ale im wolniejsza liczba klatek na sekundę, tym bardziej ruch obiektu będzie się pojawiał, ponieważ nadal porusza się o tę samą wartość co X sekund)
Ogólnie rzecz biorąc, chcesz, aby twój ruch był na sekundę. W ten sposób, bez względu na prędkość komputera, fizyka / ruch będą się zachowywać w ten sam sposób i nie będziesz mieć dziwnych błędów pojawiających się na wolniejszych urządzeniach.
I nie ma sensu z niego korzystać FixedUpdate
. Z powodu tego, o czym wspomniałem powyżej, będziesz otrzymywać tę samą wartość dla każdego połączenia (wartość ustalonego timepeptu aktualizacji) i nie wpłynie to na twoje wartości. Zdefiniowany ruch / fizyka FixedUpdate
będzie już w jednostkach na sekundę, więc go nie potrzebujesz.
Update
wywoływany jest coraz rzadziej, a twoja symulacja bardzo na tym ucierpi. Możesz nie zauważyć, gdy symulacja jest prosta, ale łatwo się przerwie, gdy tak nie jest.Od: http://unity3d.com/learn/tutorials/modules/beginner/scripting/update-and-fixedupdate
Krok czasowy zastosowany w FixedUpdate nie jest zmienny.
Jeśli gra zacznie się opóźniać, gdy się wróci, nie chcesz> 10 sekund fizyki w jednej aktualizacji, więc zazwyczaj odbywa się to w FixedUpdate, która jest wywoływana w ustalonych odstępach czasu.
Na przykład:
Gdzie:
źródło
FixedUpdate
tak naprawdę nie jest wywoływany w ustalonych odstępach czasu. Rzeczywistą naturąFixedUpdate
jest ściskanie wielu cykli fizyki w jednej klatce, jeśli gra zacznie się opóźniać i pomijać cykle, jeśli idzie za szybko, aby średnia osiągnęła ustalony czas aktualizacji. Jedność nie jest wielowątkowa, więc nie byłoby sposobu, aby zagwarantować wywołania FixedUpdate w ustalonych odstępach czasu (co dzieje się, gdy jedna FixedUpdate trwa zbyt długo). Nawet gdyby tak było, prawdopodobnie byłoby to prawie niemożliwe.Update
jest wywoływany tak szybko, jak to możliwe. Zmienna „Time.deltaTime” jest ustawiona na faktyczny czas, który upłynął od ostatniego połączenia. Jeśli opóźnienie lub coś podobnego spowalnia grę,Update
nadal będzie wywoływane tylko raz, gdy minie opóźnienie, z wysoką wartościądeltaTime
.FixedUpdate
jest wywoływany w regularnych odstępach czasu. Nigdy nie będzie wywoływany częściej niż stosunek określony w „Time.fixedDeltaTime”. Jeśli opóźnienie lub coś podobnego spowalnia grę,FixedUpdate
będzie wywoływane wiele razy w krótkich odstępach czasu, aby umożliwić dogonienie gry.Time.deltaTime
jest ustawiony na równyTime.fixedDeltaTime
przedFixedUpdate
uruchomieniem, ale jest to tylko krówka, aby ułatwić migrację kodu między nimi.Zasadniczo
Update
powinien być stosowany w przypadku zachowań interpolowanych iFixedUpdate
zachowań, które muszą być obliczane krok po kroku lub zależą od tych, które to robią, takich jak ruch oparty na fizyce. Jeśli piszesz jakąkolwiek pętlęUpdate
wzdłuż liniifor(time=0;time<=deltaTime;time+=someStep)...
, prawdopodobnie powinieneś to zrobić w FixedUpdate.źródło