Na przykład słynna gra Flappy Bird lub cokolwiek, co naprawdę się sortuje, to gracz (w tym przypadku ptak lub kamera, w zależności od tego, co wolisz) porusza się do przodu lub cały świat porusza się do tyłu (ptak zmienia tylko pozycję Y i ma stała pozycja X)?
game-mechanics
platformer
Lendrit Ibrahimi
źródło
źródło
Odpowiedzi:
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łączonymRigidBody
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:
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ątrzVector2
iVector3
(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 jednostkami1e+5
(100000
) oddalonymi od katalogu głównego / początku sceny jest bezpieczne do pracy.Ale! Od...
... 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.
źródło
Obie opcje działają.
Ale jeśli chcesz, aby niekończący się biegacz był naprawdę nieskończony, będziesz musiał zatrzymać gracza i ruszać światem. W przeciwnym razie w końcu osiągniesz granice zmiennych używanych do przechowywania pozycji X. Liczba całkowita ostatecznie się przepełni, a zmienna zmiennoprzecinkowa stanie się coraz mniej dokładna, co po pewnym czasie sprawi, że gra będzie wyglądać niezręcznie. Możesz jednak uniknąć tego problemu, używając wystarczająco dużego typu, aby nikt nie napotkał tych problemów w czasie, który można odtworzyć w jednej sesji (gdy gracz porusza się o 1000 pikseli na sekundę, 32-bitowa liczba całkowita przepełni się po 49 dniach).
Rób więc wszystko, co wydaje ci się bardziej intuicyjne.
źródło
Opierając się na odpowiedzi XenoRo , zamiast opisywanej przez siebie metody ponownego rootowania , można wykonać następujące czynności:
Stwórz okrągły bufor części generowanej nieskończonej mapy, przez którą porusza się twoja postać z pozycją zaktualizowaną o arytmetykę modulo (więc po prostu biegaj wokół okrągłego bufora). Zacznij wymieniać części bufora, gdy tylko postać opuści fragment. Równanie aktualizacji odtwarzacza wyglądałoby mniej więcej tak:
player.position = (player.position + player.velocity) % worldBuffer.width;
oto obrazowy przykład tego, o czym mówię:
Oto przykład tego, co dzieje się na zawijaniu na końcu.
Dzięki tej metodzie nigdy nie napotykasz błędów precyzji, ale może być konieczne utworzenie bardzo dużego bufora, jeśli zamierzasz to zrobić w 3D z bardzo dużej odległości widzenia (ponieważ nadal będziesz musiał widzieć przed sobą) ). Jeśli jest to ptak flappy, Twój rozmiar prawdopodobnie będzie tak duży, jak to konieczne, aby pomieścić jedną scenę na jednym ekranie, a bufor może być bardzo mały.
Zauważ, że zaczniesz uzyskiwać powtarzające się wyniki z DOWOLNYM prng, a maksymalna liczba niepowtarzalnych sekwencji generacji PRNG jest zwykle mniejsza niż długość pow (2, liczba bitów użytych wewnętrznie), w przypadku merzenne twister to nie jest duży problem, ponieważ wykorzystuje 2,5k stanu wewnętrznego, ale jeśli używasz małego wariantu, masz 2 ^ 127-1 iteracji przed powtórzeniem (lub gorzej), to wciąż jest to astronomicznie duża liczba . Możesz naprawić problemy z powtarzającym się okresem, nawet jeśli twój PRNG ma krótki okres dzięki dobrym funkcjom mieszania lawinowego dla nasion (gdy dodajesz więcej stanu pośrednio) wielokrotnie.
źródło
Jak już wspomniano i zaakceptowano, tak naprawdę zależy to od zakresu i stylu twojej gry, ale ponieważ nie zostało to wspomniane: FlappyBird przesuwa przeszkodę po ekranie, a nie gracz na całym świecie.
Spawn tworzy obiekty poza ekranem ze stałą prędkością w
Vector2.left
kierunku.źródło