Unity: Update Versus FixedUpdate

kolejny artykuł o tym, kiedy używać metod Update i FixedUpdated.

td;lr: po dość łatwym odtworzeniu problemu mieszania i dopasowywania timesteps, przekonałem się, że powinienem umieścić cały stan gry w metodach fixedupdate.

zanim przejdę do treści tego artykułu, chciałem wyjaśnić, dlaczego w pierwszej kolejności interesuje mnie jedność:

  • nie interesuje mnie ani granie, ani Tworzenie gier wideo
  • interesuje mnie budowanie użytecznych narzędzi (od wielu lat jestem programistą stron internetowych)
  • nie jestem wczesnym użytkownikiem
  • Unity to ugruntowane rozwiązanie do tworzenia wieloplatformowych doświadczeń 3D

mając to wszystko na uwadze, budowanie praktycznych rozwiązań rozszerzonej rzeczywistości (Ar) z Unity jest czymś, czego muszę się nauczyć.

jeśli chodzi o naukę jedności, nie znalazłem szczególnie przydatnych oficjalnych samouczków jedności. Uważam, że kurs Udemy Learn Unity 3D dla początkujących jest doskonały.

przeglądałem materiały i znalazłem się zawieszony na różnicy lekcji między Update i FixedUpdate. Badając nieco więcej, sednem problemu było to, że nie rozumiem następującego uzasadnienia.

Update (); … używane do regularnych aktualizacji, takich jak: ruchome obiekty inne niż fizyczne

FixedUpdate();… używane do regularnych aktualizacji, takich jak: Dostosowywanie obiektów fizyki (Rigidbody)

Unity — Update i FixedUpdate — Unity oficjalne samouczki

pojawiło się trochę więcej badań:

podsumowując, umieść całą swoją logikę gry w Update lub FixedUpdate. Nie mieszaj i dopasowuj timesteps, chyba że jesteś gotów ugryźć kulę i zaakceptować jąkanie się. Dodatkowo, zdecydowanie warto rozważyć umieszczenie całego stanu gry w FixedUpdate, używając aktualizacji wyłącznie do wprowadzania danych przez użytkownika, efektów wizualnych i interpolacji między stanami gry. Chociaż wymaga to zmiany struktury gier, jest to sprawdzona struktura projektowa z wieloma zaletami.

— KinematicSoup — Timesteps i uzyskiwanie płynnego ruchu w jedności

klip wideo w artykule ilustruje problem mieszania i dopasowywania timesteps.

zanim zastosowałem się do tej rady chciałem odtworzyć problem mieszania i dopasowywania timestepów na własną rękę.

finalna wersja projektu, której użyłem pisząc ten artykuł jest dostępna do pobrania.

Update vs FixedUpdate

musimy zacząć od podstawowego zrozumienia różnicy między metodami Update i FixedUpdate. Aby zilustrować, tworzymy pusty obiekt GameObject o nazwie Setup i dodajemy następujący komponent skryptu:

Assets/Setup.cs (niekompletny)

nasze wyjście konsoli po 3 sekundach wyglądało tak:

obserwacje:

  • aktualizacja jest wywoływana przed każdym renderowaniem; częstotliwość (liczba klatek na sekundę) różni się w zależności od złożoności renderowania i urządzenia hosta. Potężne komputery mogą osiągnąć szybkość klatek przekraczającą 150 klatek na sekundę; mój komputer programistyczny działał około 50 klatek na sekundę. Poniżej 30 fps, jest uważany za słabe doświadczenie.
  • FixedUpdate jest wywoływany przed każdą wewnętrzną aktualizacją fizyki (poruszanie się przedmiotów z powodu fizyki, np. grawitacji). Ustawiony timestep Unity domyślnie wynosi 0.02; powoduje wywołanie FixedUpdate 50 razy na sekundę.

Symulacja wolnej liczby klatek na sekundę

aby symulować wolną liczbę klatek na sekundę (10 klatek na sekundę), aktualizujemy konfigurację.skrypt cs:

Assets/Setup.cs (niekompletny)

nasze wyjście konsoli po 3 sekundach wyglądało tak:

obserwacje:

  • ustawienie vsynccount na 0 wyłącza Unity z synchronizacji renderów i częstotliwości odświeżania ekranu.
  • rzeczywista liczba klatek na sekundę może być niższa niżTARGET_FRAME_RATE ze względu na ograniczenia urządzenia hosta i złożoność renderowania.

Animacja Ręczna

aby obserwować efekty różnych animacji, zaczynamy od umieszczenia stałej kostki w celach informacyjnych.

We add our first animated GameObject (Sphere) in front of it with the following script component.

Assets/Sphere.cs (incomplete)

Running it with the normal frame rate:

Running it with 10fps frame rate:

Observations:

  • oczywiście mamy problem. Nie chcemy, aby szybkość animacji była zależna od liczby klatek na sekundę.
  • problem polega na tym, że ustawiamy prędkość na 0,1 jednostki / klatkę; chcemy, aby prędkość była mierzona w jednostkach / sekundę.

poprawka ma zapewnić prędkość w jednostkach jednostek / sekundę; 0,1 jednostek / ramkę * 50 klatek / sekundę = 5 jednostek / sekundę. Więc wykorzystamy czas.deltaTime znać czas od ostatniego połączenia do aktualizacji. Następnie przebyta odległość to prędkość * deltaTime .

aktywa/Sfera.cs (niekompletny)

z tą poprawką otrzymujemy taką samą animację bez względu na ilość klatek na sekundę (ale przy 10fps jest ona szarpana zgodnie z oczekiwaniami).

Po użyciu zmniejszonej liczby klatek na sekundę, aby zilustrować potrzebę zapewnienia prędkości w jednostkach/sekundę, możemy skomentować linie w konfiguracji.cs, który symulował Niską liczbę klatek na sekundę.

animacja w fizyce

zamiast ręcznie animować obiekt gry, możemy animować go stosując do niego fizykę. Możemy animować cylinder (poruszający się w prawo o 5 jednostek / sekundę) poprzez:

  • Tworzenie płaszczyzny (zwanej płaszczyzną)
  • Tworzenie cylindra (zwanego cylindrem)
  • Dodaj komponent Rigidbody do cylindra (i zamrożenie obrotów we wszystkich kierunkach)
  • Utwórz Materiał fizyczny, śliski, bez tarcia i zastosuj go zarówno do cylindra, jak i płaszczyzny
  • Start cylindra z prędkością początkową za pomocą komponentu skryptowego

/ cylindercs

z tym na miejscu, widzimy, że kula i cylinder poruszają się w prawo w tym samym tempie.

obserwacje:

  • pozycja kuli jest aktualizowana bezpośrednio przed renderowaniem (ręcznie w metodzie update)
  • pozycja cylindra jest aktualizowana w wewnętrznej aktualizacji fizyki.

Animacja z animacją

trzecim sposobem animacji gry jest animacja (oczywiście). Możemy animować kapsułę (próba poruszania się w prawo o 5 jednostek / sekundę) poprzez:

  • tworzenie kapsułki (zwanej kapsułą)
  • Tworzenie kontrolera animacji (również kapsułki) i dodanie jako komponentu do obiektu Gry kapsułowej.
  • tworzenie animacji (również kapsuły).
  • w kontrolerze animacji tworzy stan (Start) z jego ruchem, który ma być animacją kapsuły.
  • na koniec animujemy pozycję tak, aby pozycja pozioma kapsuły wynosiła 5 jednostek w ciągu 1 sekundy.

Mając to na miejscu, widzimy, że kula, cylinder, kapsuła (prawie) poruszają się w prawo w tym samym tempie.

obserwacje:

  • Nie wiem dlaczego, ale kapsuła poruszała się nieco szybciej niż się spodziewano; problem pojawił się przez chwilę i nie domyślił się dlaczego.
  • pozycja kapsuły może być skonfigurowana do aktualizacji przed renderowaniem (domyślnie) lub podczas aktualizacji fizyki.

implikacja szybkiej szybkości klatek

na wydajnych komputerach można osiągnąć szybkość klatek do 150 klatek na sekundę. Na tych komputerach z domyślnymi aktualizacjami fizyki 50 razy na sekundę (0,02 sekundy między aktualizacjami) elementy, które są aktualizowane przed każdym renderowaniem, są aktualizowane częściej niż te aktualizowane w aktualizacjach fizyki. Ta rozbieżność jest źródłem problemów z mieszaniem i dopasowywaniem timesteps.

chociaż nie mogę zwiększyć szybkości klatek na sekundę mojej maszyny programistycznej (ograniczone do około 50 klatek na sekundę), mogę sztucznie spowolnić aktualizacje fizyki do 10 aktualizacji na sekundę (0.1 sekund między aktualizacjami) przy użyciu ustawień projektu.

jak widać, mieszając i dopasowując timesteps odtworzyliśmy problem (niespójny ruch między elementami gry).

aby poprawić, możemy zmienić animację kapsuły na aktualizacje fizyki, a także zaktualizować komponent skryptu sfery w następujący sposób:

Assets/Sphere.cs

dzięki temu wszystkie animacje są stale aktualizowane przed każdą aktualizacją fizyki.

wreszcie, zwracamy naszą aktualizację fizyki na 50 klatek na sekundę (lub co 0,02 sekundy); osiągając zarówno spójne, jak i terminowe aktualizacje.

wnioski

mając dość łatwo odtworzony problem mieszania i dopasowywania timesteps, przekonałem się, że powinienem umieścić wszystkie stany gry w metodach fixedupdate.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.