Jak połączyć maszynę skończoną w architekturę opartą na komponentach? [Zamknięte]

23

Wydaje się, że automaty stanowe powodują szkodliwe zależności w architekturach opartych na komponentach.

Jak w szczególności obsługiwana jest komunikacja między maszyną stanu a komponentami, które zachowują się w związku z tym stanem?

Gdzie jestem w:

  • Jestem nowy w architekturze opartej na komponentach.
  • Robię grę walki, choć nie sądzę, żeby to miało znaczenie. Widzę, że moja maszyna stanów jest używana do przełączania stanów, takich jak „kucanie”, „doskakiwanie”, „blokowanie” itp.
  • Znalazłem tę technikę zarządzania stanem jako najbardziej naturalny system dla architektury opartej na komponentach, ale jest ona sprzeczna z technikami, o których czytałem: System dynamicznych obiektów obiektowych dla postaci o zmiennym zachowaniu Sugeruje to, że wszystkie komponenty aktywują / dezaktywują sami, stale sprawdzając warunek aktywacji.
  • Myślę, że takie działania jak „bieganie” lub „chodzenie” mają sens jako stany, co nie zgadza się z przyjętą odpowiedzią tutaj: /gamedev//a/7934
  • Uznałem to za przydatne, ale dwuznaczne: jak zaimplementować zachowanie w architekturze gier opartych na komponentach? Sugeruje to posiadanie osobnego komponentu, który nie zawiera niczego poza maszyną stanu. Wymaga to jednak pewnego rodzaju sprzężenia między komponentem automatu stanów i prawie wszystkimi innymi komponentami. Nie rozumiem, jak należy traktować to połączenie. Oto niektóre domysły:

    A. Komponenty zależą od maszyny stanu:
    Komponenty otrzymują odwołanie do komponentów maszyny stanu getState(), która zwraca stałą wyliczenia. Komponenty aktualizują się regularnie i sprawdzają to w razie potrzeby.

    B. Automat stanów zależy od komponentów: Komponent
    automatu stanów otrzymuje odniesienia do wszystkich monitorowanych komponentów. Pyta ich getState()metody, aby zobaczyć, gdzie są.

    C. Jakaś abstrakcja między nimi
    Używasz centrum zdarzeń? Wzorzec poleceń?

    D. Oddzielne obiekty stanu, które odwołują się do komponentów
    Używany jest wzorzec stanu. Tworzone są osobne obiekty stanu, które aktywują / dezaktywują zestaw komponentów. Maszyna stanu przełącza się między obiektami stanu.

  • Patrzę na komponenty jako implementacje aspektów . Robią wszystko, co jest potrzebne wewnętrznie, aby zrealizować ten aspekt. Wygląda na to, że komponenty powinny działać same, bez polegania na innych komponentach. Wiem, że niektóre zależności są konieczne, ale maszyny stanu wydają się kontrolować wszystkie moje komponenty.

Szczenię
źródło

Odpowiedzi:

7

Przegląd jest dość lekki, ale sprawdź te slajdy z prezentacji, którą przygotowałem dla New Game Conf w zeszłym roku:

https://docs.google.com/presentation/d/110MxOqut_y7KOW1pNwIdcccisIA3ooJwVR-xm-ecuc4/view

(patrz odpowiednie zdjęcia poniżej)

Istotą tej techniki jest połączenie wzorca listy akcji (wyjaśnionego - nieco słabo - na slajdach) z maszynami stanów behawioralnych, które działają na element gry oparty na komponentach.

Jest to w istocie to samo, co tworzenie specjalnego systemu kompozycji tylko dla zachowania AI, ukierunkowanego na rodzaje integracji między behawioralnej, której potrzebujesz dla prostszych systemów AI.

Moja ulubiona część tej konkretnej gry polegała na tym, jak mogliśmy stworzyć zupełnie nowych rodzajów wrogów, po prostu wybierając z listy wcześniej napisanych zachowań, umieszczając ich na liście akcji dla obiektu gry (rezydującego w BrainComponent) w pożądanej kolejności priorytet i wszystko po prostu działało. Dzięki liście akcji, która pozwala na blokowanie / nieblokowanie, może to zrobić naprawdę fajne rzeczy, pomimo tego, jak proste jest to wszystko do wdrożenia.

Nawet zachowania takie jak „ogłuszenie” polegały na tym, że StunBehaviorAction zepchnął się na szczyt listy akcji; jeśli zachowanie ogłuszenia zostanie aktywowane (po zaobserwowaniu, że EarsComponent obiektu gry usłyszał oszałamiający atak fali uderzeniowej), wówczas ustawia swój stan wewnętrzny na Ogłuszenie, powiedział AnimationComponent, aby odtworzył animację ogłuszenia, i ustawił jego stan akcji na Blokowanie, a jego czas na limit czasu ogłuszenia pobrany z obiektu EnemyParametersComponent obiektu gry. Ponieważ był blokowany i znajdował się na górze listy akcji, żadne inne zachowanie BehaviourAction na liście akcji nie otrzymało wywołania metody aktualizacji, więc w zasadzie zostałyby wyłączone. Po upływie limitu czasu funkcja StunBehaviorAction ponownie ustawia stan na Bezczynny, a stan akcji na Nieblokujący.

Pozostałe zachowania, które wdrożyliśmy, zostały prawie w całości zaimplementowane za pomocą jednej wewnętrznej maszyny stanów. Jedynymi dwoma, które nie miały automatów stanowych, w rzeczywistości były PatrolPathBehaviorAction (przesuwałoby serię PathAction na listę akcji, gdyby było bezczynne, co z kolei pchnęło MoveAction) i GuardHomeBehaviorAction (zawsze na dole lista akcji i zawsze przesuwałaby PathAction z powrotem do miejsca zamieszkania wroga). Każde inne zachowanie było maszyną stanu.

Slajd 10 Slajd 25 Slajd 26

Sean Middleditch
źródło
Jaka jest podstawowa różnica między „zachowaniami” a „działaniami”?
Pup
1
@Pup: Z perspektywy kodu, gdy go zbudowałem, zachowanie jest działaniem. Z punktu widzenia koncepcyjnego Akcje są zwykle przejściowe - istnieją tylko do „ukończenia” - podczas gdy Zachowania są wieczne i nigdy nie są usuwane z listy. Widziałem inny zespół budujący podobny system, ale z dwiema listami, jedną dla Akcji i jedną dla Zachowań, która działa wystarczająco dobrze. Lubię jednak mieć możliwość blokowania określonych zachowań przez akcję za pomocą masek bitowych i grupowania (linie, myślę, że nazwałem je na slajdach). Przepraszam, że grafika środkowego slajdu jest taka zła. :)
Sean Middleditch,
3

W poprzedniej firmie, dla której pracowałem, mieliśmy system oparty na komponentach z opartą na stanie sztuczną inteligencją. Mieliśmy komponent AI, który kontrolował wszystkie zachowania tego obiektu / jednostki. Gdy sztuczna inteligencja była aktywna, jak wędrówki, atakowanie itp., Otrzymywał aktualizację dla każdej klatki, aby wykonać potrzebną logikę. Kiedy AI pracowało na biegu jałowym lub nie poruszało się, komponent był dezaktywowany i nie aktualizował każdej klatki. Po dezaktywacji komponent nadal może odbierać wiadomości oparte na zdarzeniach, więc otrzyma komunikat o czymś takim, jak gracz wchodzący w jego promień agro, i może odpowiedzieć na to, reaktywując komponent AI, aby mógł dokonywać aktualizacji opartych na ramkach.

Komponent AI ma podskładniki, które może tworzyć i niszczyć w locie, w zależności od rodzaju wykonywanych czynności. Na przykład, jeśli wędrował, mógłby utworzyć wędrujący podskładnik i zaktualizować tę ramkę podczas wędrówki, a następnie, gdy byłby wędrowny, zamknąłby ten podskładnik i otworzył podskładnik ataku. Komponent AI powinien być niezależny od wszystkich innych komponentów obiektu. Na przykład mieliśmy komponent wejściowy, który po prostu sprawdzałby wartości ruchu na jednostce. Pytanie, które zadał, było odpowiedzią zarówno na obiekty ludzkie, jak i AI. To pozwoliło komponentowi AI po prostu ustawić sobie wartości ruchu podczas takich rzeczy, jak wędrówka, na której komponent wejściowy mógłby się wychwycić, tak jak komponent sterowany przez człowieka ustawiałby wartości, na których komponent wejściowy mógłby się rejestrować.

Nic Foster
źródło
Więc podzespoły AI faktycznie wykonują pracę? Czy istniały jako komponenty bytu, na tym samym poziomie co komponent AI?
Pup
Podzespoły w naszym silniku były częścią podstawowej klasy komponentów. Tak więc każdy Component, który pochodzi BaseComponent, może mieć na sobie dowolną liczbę SubComponents. Update()Metoda BaseComponentby sprawdzić listę podkomponenty i zadzwonić Update()na tych. Subcomponentsbyły całkowicie opcjonalne, więc BaseComponentmoże ich nie mieć. Ponadto wszelkie wiadomości, które trafiły do ​​komponentu, były również kierowane do podskładników.
Nic Foster
1

Nie jest jasne, co rozumiesz przez składniki, ponieważ twoje terminy są bardzo niejasne, bez konkretnych przykładów. Często byty gry budowane są przy użyciu kompozycji, a nie dziedziczenia. W ten sposób możesz zrobić z nich coś, co może odnieść obrażenia, dodając element zdrowia do bytu lub możesz ożywić je, dodając element ożywiony. Można również umieścić AI w takim elemencie. W twoim komponencie AI będzie logika decyzyjna, a jeśli martwisz się sprzężeniem tego z większością innych kodów w systemie, możesz zebrać informacje na tablicy, do której logika AI ma dostęp tylko. Istnieje również kwestia zależności od wyników systemu AI. Zasadniczo twoja AI kontroluje byt i ta kontrola potrzebuje interfejsu. Jedną przydatną koncepcją jest kontroler lub gamepad. Twoja sztuczna inteligencja może wypełnić podobną strukturę, którą wypełniłby gamepad gracza (chociaż może mieć dodatkowe „przyciski” dla określonych umiejętności). Teraz ta struktura może zostać przekazana do animowanego komponentu, który zinterpretuje ją i wybierze odpowiednie animacje do odtworzenia. Różne podskładniki AI mogą nawet pisać do różnych pól struktury lub do tych samych pól o różnych priorytetach. Na przykład celowanie i chodzenie. Różne podskładniki AI mogą nawet pisać do różnych pól struktury lub do tych samych pól o różnych priorytetach. Na przykład celowanie i chodzenie. Różne podskładniki AI mogą nawet pisać do różnych pól struktury lub do tych samych pól o różnych priorytetach. Na przykład celowanie i chodzenie.

Jesse Cluff
źródło