Byłem trochę ciekawy, jak można zaimplementować powtórkę w grze.
Początkowo myślałem, że będzie tylko lista poleceń wszystkich działań gracza / ai, które zostały podjęte w grze, a następnie „gra” ponownie i pozwala silnikowi renderować się jak zwykle. Mam jednak spojrzał na powtórkach w FPS / RTS gry, a po wnikliwej kontroli nawet rzeczy takie jak cząstki i graficznych / słyszalnych trzasków są spójne (i te usterki są na ogół w spójne).
Więc jak to się dzieje. W grach ze stałym kątem kamery pomyślałem, że może po prostu zapisać każdą klatkę całej sceny w strumieniu, który zostanie zapisany, a następnie po prostu powtórzy strumień z powrotem, ale to nie wydaje się wystarczające dla gier, które pozwalają na wstrzymywanie i poruszanie kamerą na około. Musiałbyś przechowywać lokalizacje wszystkiego na scenie w każdym momencie (nie?). Tak więc w przypadku cząsteczek jest to dużo danych do przekazania, co wydaje się znaczącym obniżeniem wydajności gry podczas grania.
źródło
Odpowiedzi:
Myślę, że twoja początkowa myśl była poprawna. Aby utworzyć powtórkę, przechowujesz wszystkie dane wejściowe otrzymane od użytkownika (wraz z numerem klatki, w której zostało odebrane) wraz z początkowymi początkami dowolnych generatorów liczb losowych. Aby odtworzyć grę, resetujesz swoje PRNG za pomocą zapisanych seedów i zasilasz silnik gry tą samą sekwencją danych wejściowych (zsynchronizowanych z numerami klatek). Ponieważ wiele gier aktualizuje stan gry na podstawie czasu, jaki upływa między klatkami, może być konieczne zapisanie długości każdej klatki.
źródło
Starcraft i Starcraft: Brood War miały funkcję powtórki. Po zakończeniu meczu możesz zapisać powtórkę, aby wyświetlić ją później. Podczas powtórki można było przewijać mapę i klikać jednostki i budynki, ale nie zmieniać ich zachowania.
Pamiętam, jak oglądałem powtórkę meczu, który był rozegrany w oryginalnej grze, ale powtórka była oglądana w Brood War. Dla tych, którzy nie są zaznajomieni, Brood War zawiera wszystkie oryginalne jednostki i budynki, a także wiele nowych. W oryginalnej grze gracz pokonał komputer, tworząc jednostki, którym komputer nie mógł łatwo przeciwdziałać. Kiedy grałem w powtórkę w Brood War, komputer miał dostęp do różnych jednostek, które tworzył i wykorzystywał do pokonania gracza. Tak więc ten sam plik powtórki skutkował innym zwycięzcą w zależności od tego, która wersja Starcraft odtwarzała plik.
Zawsze fascynowała mnie ta koncepcja. Wydawałoby się, że funkcja powtórki działała poprzez rejestrowanie wszystkich danych wejściowych odtwarzacza i zakładała, że komputer za każdym razem będzie reagował na te bodźce w dokładnie taki sam sposób. Kiedy dane wejściowe gracza zostały wprowadzone do oryginalnego odtwarzacza Starcraft, gra przebiegała dokładnie tak, jak w pierwotnym meczu. Gdy te same dane wprowadzono do odtwarzacza Brood War, komputer zareagował inaczej, stworzył silniejsze jednostki i wygrał grę.
Coś, o czym należy pamiętać, pisząc silnik powtórek.
źródło
Istnieją dwie główne metody:
To zależy od tego, co chcesz zrobić. Czasami przechowywanie zdarzeń jest lepsze, ponieważ zwykle zajmuje to znacznie mniej pamięci. Z drugiej strony, jeśli chcesz zapewnić powtórki, które można odtwarzać z różnymi prędkościami iz różnych punktów początkowych, lepiej jest przechowywać stany. Podczas zapisywania stanów możesz również zdecydować, czy zapisywać je po każdym wydarzeniu, czy np. Tylko 12 lub 25 razy na sekundę - może to zmniejszyć rozmiar powtórki i ułatwić przewijanie ich do tyłu / do przodu.
Zauważ, że „stan” nie oznacza stanu graficznego. Bardziej jak pozycje jednostek, stan zasobów i tak dalej. Rzeczy takie jak grafika, układy cząstek itp. Są zwykle deterministyczne i mogą być przechowywane jako „animacja X, czas Y: Z”.
Czasami powtórki są używane jako schemat anticheating. Zatem przechowywanie wydarzeń jest tutaj prawdopodobnie najlepsze.
źródło
Technicznie rzecz biorąc, powinieneś napisać swój silnik tak, aby był deterministyczny, czyli nie ma przypadkowości. Zakładając, że postać w grze celuje w ramię przeciwnika i strzela z broni, wówczas we wszystkich przypadkach należy zadać przeciwnikowi taką samą ilość obrażeń.
Zakładając, że bomba zdetonuje się w miejscu X, cząstki wytwarzane przez tę eksplozję powinny zawsze dawać ten sam efekt wizualny. Jeśli potrzebujesz losowości, utwórz zestaw liczb losowych, wybierz wartość początkową podczas gry i zapisz tę wartość początkową w powtórce.
Ogólnie rzecz biorąc, losowość w grze to zły pomysł. Nawet w przypadku gier wieloosobowych nie możesz mieć połowy graczy w stanie widzieć wokół eksplozji, podczas gdy inni nie mogą po prostu dlatego, że nie otrzymali odpowiedniej losowej wartości.
Niech wszystko będzie deterministyczne, a powinno być dobrze.
źródło
Biorąc pod uwagę stan początkowy i serię działań z sygnaturami czasowymi , po prostu przejdź przez sekwencję, ponieważ nagrane działania mają się wydarzyć i odtworzyć.
Aby przypadkowe zdarzenia wystąpiły ponownie dokładnie to samo, użyj zapoczątkowanych liczb pseudolosowych i zapisz ziarno w pliku powtórki.
Dopóki używasz tego samego algorytmu do generowania liczb losowych z materiału siewnego, możesz odtworzyć wszystkie zdarzenia tak, jak wystąpiły w grze na żywo, bez konieczności wykonywania pełnych migawek stanu gry.
Będzie to wymagało oglądania powtórek po kolei , ale jest to całkiem normalne w przypadku powtórek z gry (patrz Starcraft 2). Jeśli chcesz zezwolić na swobodny dostęp do osi czasu, możesz wykonywać pełne migawki stanu w ustalonych odstępach czasu (powiedzmy co minutę), aby przeskakiwać po osi czasu z określoną szczegółowością.
źródło
NVidia PhysX (silnik symulacji fizyki, który jest często używany w grach) jest w stanie rejestrować pełny stan fizycznej sceny w czasie. Obejmuje to wszelkie dane wejściowe z silnika gry, co oznacza, że nie musisz śledzić losowych nasion, jak sugerowali inni. Jeśli weźmiesz ten zrzut sceny, możesz go odtworzyć w zewnętrznym narzędziu (dostarczonym przez firmę NVidia), które jest bardzo przydatne do śledzenia problemów z modelami fizycznymi. Jednak możesz również użyć tego samego strumienia fizyki do sterowania silnikiem graficznym, który pozwoliłby ci wtedy na normalne sterowanie kamerą, ponieważ zapisywana była tylko fizyka sterująca grafiką. W wielu grach dotyczy to również efektów cząsteczkowych (PhysX zawiera kilka bardzo wyrafinowanych systemów cząsteczek). Jeśli chodzi o dźwięk, zgaduję, że jest on nagrany dosłownie (jako strumień dźwiękowy), ale ja '
źródło
Twój oryginalny pomysł jest słuszny, a dla naprawdę złożonych efektów nie są one pamiętane wyłącznie. Na przykład, system powtórek Warcraft 3 nie przechowuje stanu animacji, ani efektów cząsteczkowych w przypadku efektów losowych itp. Poza tym WIĘKSZOŚĆ rzeczy można obliczyć obliczeniowo od punktu początkowego w sposób deterministyczny, więc dla większości systemów używających zmiennych losowych (na przykład eksplozji cząstek, która daje losowe przesunięcie), wszystko, czego potrzebujesz, to czas efektu i losowe ziarno. Możesz wtedy ponownie wygenerować efekt, nie wiedząc tak naprawdę, jak będzie wyglądał ... wiedząc, że przechodzi przez deterministyczną ścieżkę kodu.
Myśląc o tym czysto koncepcyjnie, aby odtworzyć oś czasu zdarzeń, potrzebujesz tylko działań użytkownika. Program zareaguje dokładnie w ten sam sposób, poza przypadkami zmiennych losowych. W tym scenariuszu możesz albo zignorować losowość (czy NAPRAWDĘ ma to znaczenie, jeśli efekty wyglądają DOKŁADNIE tak samo, czy też mogą zostać losowo wygenerowane ponownie) lub zapisać wartość ziarna i sfałszować losowość.
źródło
Wrzuć moje dwa pensy.
W zależności od tego, czego chcesz, powtórka może zostać wykonana przez
W większości przypadków ludzie chcą interaktywnej powtórki, więc 2. jest najlepszym rozwiązaniem. Następnie, w zależności od twoich ograniczeń, istnieje wiele sposobów optymalizacji tego procesu
To naprawdę fascynujący temat. Pamiętam, że jeden tytuł premierowy oryginalnego Xbox Wreckless miał dobrą funkcję odtwarzania. Niestety, niejednokrotnie powtórka się zepsuła;)
o tak, jak ktokolwiek mógł zapomnieć o Blinx Time Sweeper ! świetna interaktywna powtórka, która została włączona do rzeczywistej mechaniki gry!
* = wydaje się, że są pewne uwagi dotyczące kroków w czasie. Używam tutaj „symulacji”, aby uchwycić tę funkcję. w istocie Twój silnik musi być w stanie wytwarzać dyskretne ramy czasu. nawet jeśli przetwarzanie klatki powtórki trwa dłużej lub krócej niż oryginał, system musi dostrzec, że minęła ta sama delta czasu. oznacza to rejestrowanie przedziału czasowego klatki z każdym zarejestrowanym wejściem i dostarczanie tej delty do zegara silnika.
źródło
Być może mógłbyś po prostu zapisać stos poleceń wysyłanych przez każdego gracza. Zamiast więc oszczędzać, że bomba wybuchnie w określonym momencie lub w określonym czasie, lub że jakiś samochód zostanie zniszczony, po prostu zapisujesz naciśnięcia klawiszy wysyłane przez każdego gracza. Następnie w powtórce po prostu symulujesz grę, tak jak by się to stało w przypadku tych pras. Wydaje mi się, że może to zająć mniej miejsca, ale nigdy nie pracowałem nad takim systemem powtórek.
Ciekawe pytanie. Byłbym zainteresowany, jak to się robi w profesjonalnych grach.
źródło
Dan Bryant
Dokładnie to pomyślałem na początku, kiedy próbowałem dowiedzieć się, jak to zrobili, aby gra była odtwarzana zawsze tak samo za każdym razem. Z Doomem pomyślałem, jak przypadkowe poszły zdjęcia: D. Przechowuj dowolną liczbę losową, odkryłem, że może to być rozwiązanie. To było zanim natknąłem się na dokument pdf o technologii Crysis. Niektóre tekstury są tam szumiące i usposobienie trawy lub drzewa, wydawało się, że używają pseudorandomizacji z ustalonymi odwracalnymi nasionami, aby zrobić to, abyś nie widział zmienionego rozmieszczenia hałasu, drzew i trawy za każdym razem, gdy spojrzysz!
Unikanie w tym samym czasie przechowywania milionów drzew i pozycji trzonów trawiastych. Pozornie pseudolosowa sekwencja może powtórzyć to samo w dowolnym momencie, ponieważ logika jest ustalona, aby po prostu utworzyć fałszywą statystycznie losową sekwencję liczb.
źródło
Problem spójnej powtórki jest taki sam (no cóż, łatwiejszy), jak w przypadku spójnej gry wieloosobowej.
Jak inni wspomnieli wcześniej, powtórki w grach RTS są zapisywane poprzez nagrywanie wszystkich danych wejściowych (ma to wpływ. Przewijanie nie ma żadnego efektu). Tryb wieloosobowy również przesyła wszystkie dane wejściowe
Nagrywanie wszystkich danych wejściowych, a nie tylko przypuszczenie - jest biblioteka do czytania powtórek Warcraft3, która to ujawnia.
input zawiera sygnatury czasowe dla tej odpowiedzi.
źródło
Uważam, że przy pewnych przyrostach gra zrobi migawkę stanu wszystkiego (WSZYSTKIEGO). Wtedy, gdy ma miejsce powtórka, do wypełnienia "dziur" można użyć prostego użycia interpolacji liniowej. Przynajmniej tak mi się wydaje.
Masz rację, że rejestrowanie wejść byłoby niewiarygodne / nie gwarantuje takiego samego wyjścia. Gra zdecydowanie musi na bieżąco śledzić stan wszystkich obiektów (lub przynajmniej tych ważnych)
źródło