(Możesz chcieć wiedzieć o terminach „łatanie małp” lub „wykaczanie kaczek”, jeśli tylko dla humorystycznego obrazu mentalnego.)
Poza tym: jeśli Twoim celem jest skrócenie czasu iteracji dla zmian „zachowania”, wypróbuj kilka metod, które zapewnią ci najwięcej możliwości, i połącz je ładnie, aby umożliwić więcej tego w przyszłości.
(To wyjdzie na trochę styczne, ale obiecuję, że wróci!)
- Zacznij od danych i zacznij od małego: przeładuj na granicach („poziomach” lub podobnych), a następnie przejdź do korzystania z funkcji systemu operacyjnego, aby otrzymywać powiadomienia o zmianie plików lub po prostu regularnie sondować .
- (W celu uzyskania punktów bonusowych i krótszych czasów ładowania (ponownie, zmniejszając czas iteracji) zajrzyj do wypalania danych .)
- Skrypty są danymi i umożliwiają iterację zachowania. Jeśli używasz języka skryptowego, masz teraz powiadomienia / możliwość ponownego załadowania tych skryptów, zinterpretowanych lub skompilowanych. Możesz także podłączyć tłumacza do konsoli w grze, gniazda sieciowego lub podobnego elementu, aby zwiększyć elastyczność środowiska wykonawczego.
- Kod może być także danymi : Twój kompilator może obsługiwać nakładki , biblioteki współdzielone, biblioteki DLL i tym podobne. Możesz teraz wybrać „bezpieczny” czas na rozładowanie i ponowne załadowanie nakładki lub biblioteki DLL, zarówno ręcznej, jak i automatycznej. Pozostałe odpowiedzi są tutaj szczegółowo opisane. Należy pamiętać, że niektóre warianty tego mogą powodować problemy z weryfikacją podpisu kryptograficznego, bitem NX (brak wykonania) lub podobnymi mechanizmami bezpieczeństwa.
- Rozważ głęboki, wersjonowany system zapisu / ładowania . Jeśli możesz bezpiecznie zapisać i przywrócić swój stan nawet w obliczu zmian kodu, możesz zamknąć grę i uruchomić ją ponownie z nową logiką dokładnie w tym samym punkcie. Łatwiej powiedzieć niż zrobić, ale jest to wykonalne i jest znacznie łatwiejsze i bardziej przenośne niż szturchanie pamięci w celu zmiany instrukcji.
- W zależności od struktury i determinizmu gry możesz nagrywać i odtwarzać . Jeśli nagranie jest tuż nad „poleceniami gry” (na przykład grą karcianą), możesz zmienić cały kod renderowania i odtworzyć nagranie, aby zobaczyć zmiany. W przypadku niektórych gier jest to tak „łatwe”, jak rejestracja niektórych parametrów początkowych (np. Losowego początku), a następnie działań użytkownika. Dla niektórych jest to o wiele bardziej skomplikowane.
- Staraj się skracać czas kompilacji . W połączeniu z wyżej wymienionymi systemami zapisu / ładowania lub nagrywania / odtwarzania, a nawet z nakładkami lub bibliotekami DLL, może to zmniejszyć twój zwrot bardziej niż jakakolwiek inna rzecz.
Wiele z tych punktów jest korzystnych, nawet jeśli nie uda ci się przeładować ani danych, ani kodu.
Wspierające anegdoty:
Na dużym PC RTS (~ 120-osobowy zespół, głównie C ++), istniał niesamowicie głęboki system oszczędzania stanu, który był wykorzystywany do co najmniej trzech celów:
- „Płytkie” zapisanie zostało wprowadzone nie na dysk, ale do silnika CRC, aby zapewnić, że gry wieloosobowe pozostaną w symulacji blokowania jeden CRC co 10-30 klatek; zapewniło to, że nikt nie oszukuje i kilka sekund później wyłapał błędy związane z desynchronizacją
- Jeśli i kiedy wystąpi błąd desynchronizacji dla wielu graczy, w każdej klatce wykonywany jest wyjątkowo głęboki zapis i ponownie przekazywany do silnika CRC, ale tym razem silnik CRC wygeneruje wiele CRC, każda dla mniejszych partii bajtów. W ten sposób może dokładnie powiedzieć, która część stanu zaczęła się rozchodzić w ostatniej ramce. Zauważyliśmy nieprzyjemną różnicę między „domyślnym trybem zmiennoprzecinkowym” między procesorami AMD i Intel.
- Normalny zapis głębokości może nie zapisać np. Dokładnej klatki animacji, w którą grała twoja jednostka, ale uzyskałby pozycję, zdrowie itp. Wszystkich twoich jednostek, umożliwiając zapisywanie i wznawianie w dowolnym momencie podczas gry.
Od tego czasu używałem deterministycznego nagrywania / odtwarzania w grze karcianej C ++ i Lua dla DS. Połączyliśmy się z interfejsem API zaprojektowanym dla AI (po stronie C ++) i zarejestrowaliśmy wszystkie działania użytkownika i AI. Wykorzystaliśmy tę funkcję w grze (aby zapewnić powtórkę dla odtwarzacza), ale także w celu zdiagnozowania problemów: gdy wystąpił awaria lub dziwne zachowanie, wystarczyło pobrać plik zapisu i odtworzyć go w kompilacji debugowania.
Od tego czasu używałem nakładek więcej niż kilka razy i połączyliśmy to z naszym „automatycznie przeglądającym ten katalog i przesyłam nowe treści do systemu podręcznego”. Wszystko, co musielibyśmy zrobić, to opuścić scenę przerywnikową / poziom / cokolwiek i wrócić i nie tylko nowe dane (duszki, układ poziomów itp.) Załadują się, ale także nowy kod w nakładce. Niestety, staje się to coraz trudniejsze w przypadku nowszych urządzeń przenośnych ze względu na ochronę przed kopiowaniem i mechanizmy zapobiegające hakowaniu, które specjalnie traktują kod. Nadal jednak robimy to dla skryptów lua.
Last but not least: możesz (i ja, w różnych bardzo małych szczególnych okolicznościach) zrobić trochę dziurkowania, bezpośrednio łatając kody instrukcji. Działa to najlepiej, jeśli jesteś na stałej platformie i kompilatorze, a ponieważ jest prawie nie do utrzymania, bardzo podatny na błędy i ograniczony w tym, co możesz szybko osiągnąć, używam go głównie do zmiany trasy kodu podczas debugowania. To nie nauczy Cię cholernie dużo o swojej zestaw instrukcji architektury w pośpiechu, choć.