Nie zgadzam się z odpowiedzią Filipa ; a przynajmniej z tym, jak to przedstawił. Sprawia wrażenie, że lepszym pomysłem jest poruszanie się po świecie wokół gracza; kiedy jest dokładnie odwrotnie. Oto moja własna odpowiedź ...
Obie opcje mogą działać, ale generalnie złym pomysłem jest „odwrócenie fizyki” poprzez przenoszenie świata wokół gracza, a nie gracza na całym świecie.
Utrata wydajności / odpady:
Świat zwykle będzie miał wiele przedmiotów; wielu, jeśli nie większość, statycznych lub śpiących. Gracz będzie miał jeden lub względnie mało obiektów. Poruszanie całym światem wokół gracza oznacza przenoszenie wszystkiego na scenie oprócz gracza. Obiekty statyczne, śpiące obiekty dynamiczne, aktywne obiekty dynamiczne, źródła światła, źródła dźwięku itp .; wszystkie muszą zostać przeniesione.
To (oczywiście) znacznie droższe niż przenoszenie tylko tego, co się faktycznie porusza (gracz i może jeszcze kilka innych rzeczy).
Konserwowalność i rozszerzalność:
Poruszanie się po świecie wokół gracza sprawia, że świat (i wszystko w nim) jest punktem, w którym rzeczy dzieją się najbardziej aktywnie. Każdy błąd lub zmiana w systemie oznacza, że potencjalnie wszystko się zmienia. To nie jest dobry sposób na robienie rzeczy; chcesz, aby błędy / zmiany były jak najbardziej odizolowane, abyś nie dostał nieoczekiwanego zachowania w miejscu, w którym nie wprowadziłeś zmian.
Z tym podejściem wiąże się także wiele innych problemów. Na przykład łamie wiele założeń dotyczących tego, jak rzeczy mają działać na silniku. Na przykład nie będziesz mógł używać dynamiki RigidBody
do niczego innego niż odtwarzacz; ponieważ obiekt z dołączonym RigidBody
nie ustawionym kinematyki będzie zachowywał się nieoczekiwanie podczas ustawiania pozycji / obrotu / skali (co robiłbyś dla każdej klatki, dla każdego obiektu w scenie, z wyjątkiem odtwarzacza 😨)
Odpowiedzią jest więc tylko przesunąć gracza!
Cóż ... tak i nie . Jak wspomniano w odpowiedzi Filipa, w grze typu „nieskończony biegacz” (lub dowolnej grze z dużym bezproblemowym obszarem do eksploracji) zbytnie oddalanie się od pochodzenia ostatecznie wprowadziłoby zauważalne FPPE ( błędy precyzji zmiennoprzecinkowej ), a ponadto przepełnienie typu liczbowego, albo powodując awarię gry, albo, w gruncie rzeczy, dym świat gry ... pęk na sterydach! 😵 (ponieważ do tego momentu FPPE sprawi, że gra będzie już na „normalnym” crackie)
Rzeczywiste rozwiązanie:
Nie rób ani i rób oba! Powinieneś utrzymać świat w bezruchu i poruszać nim gracza. Ale „zrootuj” zarówno gracza, jak i świat, gdy gracz zacznie się zbyt daleko od korzenia (pozycji [0, 0, 0]
) sceny.
Jeśli utrzymasz względną pozycję rzeczy (gracza względem otaczającego go świata) i wykonasz ten proces w ramach pojedynczej aktualizacji ramki, (rzeczywisty) gracz nawet tego nie zauważy!
Aby to zrobić, masz dwie podstawowe opcje:
- Przenieś gracza do korzenia sceny i przenieś fragment świata na jego nową pozycję względem gracza.
- Pomyśl o świecie jak o siatce; przesuń część siatki, w której znajduje się gracz, do korzenia i przenieś gracza do nowej pozycji względem tej części siatki.
Oto przykład tego procesu w akcji
Ale jak daleko jest za daleko?
Jeśli spojrzysz na kod źródłowy Unity, używają one 1e-5
( 0.00001
) jako podstawy do rozważenia dwóch wartości zmiennoprzecinkowych „równych”, wewnątrz Vector2
i Vector3
(typy danych odpowiedzialne za pozycje obiektów, obrót i skale [euler-]). Ponieważ utrata precyzji zmiennoprzecinkowej odbywa się w obie strony od zera, można bezpiecznie założyć, że wszystko pod jednostkami 1e+5
( 100000
) oddalonymi od katalogu głównego / początku sceny jest bezpieczne do pracy.
Ale! Od...
- Bardziej odpowiednie jest stworzenie systemu do automatycznego zarządzania tymi procesami ponownego rootowania.
- Jakakolwiek jest Twoja gra, nie ma potrzeby, aby ciągła „część” świata miała 100 000 jednostek (metrów [?]).
... to prawdopodobnie dobrym pomysłem jest ponowne rootowanie znacznie wcześniej / częściej niż ten znak 100000 jednostek. Przykładowy film, który podałem, wydaje się robić to na przykład co 1000 jednostek.