Mam problemy z implementacją skryptów w silniku gry. Mam tylko kilka wymagań: powinien być intuicyjny, nie chcę pisać niestandardowego języka, analizatora składni i interpretera oraz nie chcę używać wątków. (Jestem pewien, że istnieje prostsze rozwiązanie; nie potrzebuję kłopotów z wieloma wątkami logiki gry.) Oto przykładowy skrypt w Pythonie (inaczej pseudokod):
def dramatic_scene(actors):
alice = actors["alice"]
bob = actors["bob"]
alice.walk_to(bob)
if bob.can_see(alice):
bob.say("Hello again!")
else:
alice.say("Excuse me, Bob?")
Ten epicki kawałek historii stwarza problemy z implementacją. Nie mogę po prostu ocenić całej metody na raz, ponieważ walk_to
wymaga to czasu gry. Jeśli powróci od razu, Alice zacznie podchodzić do Boba i (w tej samej ramce) przywitać się (lub przywitać). Ale jeśli walk_to
zadzwoni blokujący, który powróci, gdy dotrze do Boba, moja gra utknie, ponieważ blokuje ten sam wątek wykonania, który zmusiłby Alice do chodzenia.
Zastanawiałem się nad tym, by każda funkcja kolejkowała akcję - alice.walk_to(bob)
przesuwałaby obiekt do kolejki, która odpadałaby po tym, jak Alice dotarła do Boba, gdziekolwiek był. Jest to bardziej subtelnie zepsute: if
gałąź jest oceniana natychmiast, więc Bob może powitać Alice, nawet jeśli odwróci się do niej plecami.
Jak inne silniki / ludzie radzą sobie ze skryptami bez tworzenia wątków? Zaczynam szukać pomysłów w obszarach nie przeznaczonych dla twórców gier, takich jak łańcuchy animacji jQuery. Wydaje się, że powinny istnieć dobre wzorce dla tego rodzaju problemów.
Odpowiedzi:
Sposób, w jaki robi to Panda, polega na wywołaniach zwrotnych. Zamiast blokowania byłoby to coś w rodzaju
Posiadanie pełnego wywołania zwrotnego pozwala na łączenie tego rodzaju zdarzeń tak głęboko, jak chcesz.
EDYCJA: Przykład JavaScript, ponieważ ma lepszą składnię dla tego stylu:
źródło
Termin, którego chcesz tu szukać, to „ coroutines ” (i zazwyczaj jest to słowo kluczowe języka lub nazwa funkcji
yield
).Wdrożenie będzie zależeć przede wszystkim od Twojego języka. W przypadku gry chcesz, aby implementacja była jak najlżejsza (lżejsza niż nici, a nawet włókna). Strona Wikipedii (link) zawiera linki do różnych implementacji specyficznych dla języka.
Słyszałem, że Lua ma wbudowane wsparcie dla coroutines. Podobnie GameMonkey.
UnrealScript implementuje to za pomocą tak zwanych „stanów” i „funkcji ukrytych”.
Jeśli używasz C #, możesz spojrzeć na ten post na blogu autorstwa Nicka Gravelyn.
Dodatkowo pomysł „łańcuchów animacji”, choć nie to samo, jest praktycznym rozwiązaniem tego samego problemu. Nick Gravelyn ma również implementację tego języka C # .
źródło
yield return walk_to();
w swoim skrypcie.brak wątków jest mądry.
Większość silników do gier działa jako seria etapów modułowych z pamięcią sterującą każdym etapem. W przypadku „przejścia do przykładu” zazwyczaj masz etap sztucznej inteligencji, w którym chodzone postacie znajdują się w stanie, w którym nie powinny szukać wrogów do zabicia, etap animacji, w którym powinni uruchomić animację X, etap fizyki (lub etap symulacji), gdzie aktualizowana jest ich rzeczywista pozycja itp.
w powyższym przykładzie „alicja” jest aktorem złożonym z kawałków, które żyją na wielu z tych etapów, więc blokujący aktor call.walk_to (lub coroutine, który wywołujesz next () raz na klatkę) prawdopodobnie nie miałby odpowiedniego kontekstu podejmować wiele decyzji.
Zamiast tego funkcja „start_walk_to” prawdopodobnie zrobiłaby coś takiego:
Następnie główna pętla uruchamia tik ai, tik fizyki, tik animacji i tik przerywnika, a przerywnik aktualizuje stan każdego z podsystemów w silniku. System przerywników filmowych powinien zdecydowanie śledzić, co robi każdy ze scen przerywnikowych, a system oparty na coroutine dla czegoś liniowego i deterministycznego, jak na przykład scenka przerywnikowa, może mieć sens.
Powodem tej modułowości jest to, że po prostu utrzymuje rzeczy ładne i proste, a dla niektórych systemów (takich jak fizyka i sztuczna inteligencja), musisz znać stan wszystkiego w tym samym czasie, aby poprawnie rozwiązać problemy i utrzymać grę w spójnym stanie .
mam nadzieję że to pomoże!
źródło