W ramach mojego obecnego projektu wdrożyłem system oparty na komponentach / jednostkach , zasadniczo przestrzegając większości najlepszych praktyk w tym raczej nieokreślonym obszarze .
Mam więc (nieco rozszerzone) byty , które są w zasadzie int
identyfikatorem, czytelną dla człowieka nazwą, std::map
składników i long
„wskaźnikiem typu”, który służy do pokazania, które składniki są obecne (mam moc dwóch enum
dla wszystkich składników typy i za każdym razem, gdy komponent jest dodawany do Entity, automatycznie zmieniam tę długość za pomocą operacji bitowych, porównuję tę odpowiedź ).
Są jeszcze Komponenty , również dość proste: int
ID, enum
jako typ komponentu, wskaźnik encji nadrzędnej i std::map
wszystkie właściwości, które posiada ten komponent.
Wreszcie niektóre systemy / menedżery, które obsługują faktyczne przetwarzanie logiki. Najpierw sprawdzają, czy aktualnie przetwarzana jednostka ma pasujący long
„wskaźnik typu” = obecne są wszystkie niezbędne komponenty dla tego systemu. W razie potrzeby uzyskuje dostęp do niektórych właściwości i albo bezpośrednio wywołuje niektóre funkcje w odpowiednim składniku, albo wysyła niektóre wiadomości (za pośrednictwem programu rozsyłającego wiadomości).
Konkluzja: Do tej pory raczej standardowy system oparty na zdarzeniach oparty na komponentach / jednostkach w połączeniu z podejściem opartym na danych (porównaj, komponenty nie mają zakodowanych na stałe zmiennych danych, ale zamiast tego ogólną mapę, jako (niektóre) komponenty / archetypy komponentów zostaną później odczytane z plików z opcją dodania dodatkowych danych, które nie są częścią rzeczywistego kodu komponentu.
Teraz chciałbym również wprowadzić drzewa zachowań (oparte na AiGameDev BTSK ) do tego projektu, ale nie jestem pewien, czy i jak powinny one być powiązane z już istniejącymi komponentami lub jak ogólnie zintegrować te projekty.
Przychodzi mi na myśl kilka powiązanych pomysłów / punktów / pytań:
Moje BT zostaną odczytane z plików (ponownie). Obecnie trudno mi się przekonać, jak najlepiej wykonać połączenie między
BT Action
drzewem w tym drzewie a rzeczywistym kodowaniem w mojej aplikacji. Czy powinienem stworzyć mapę między nazwami akcji użytymi w plikach BT a wskaźnikiem funkcji do rzeczywistej implementacji logiki? Jakie jest typowe podejście do rozwiązania tego problemu?Zakładam, że będę musiał stworzyć BT dla wszystkich moich różnych
Entity
typów (więc dla każdej kombinacji elementów związanych z logiką gry / AI, jak wskazuje mój wielokrotnie wspomniany długi „wskaźnik typu”). W związku z tym nie ma sensu umieszczanieBT Action
implementacji w komponentach, ponieważ najprawdopodobniej w akcję będzie zaangażowanych wiele komponentów, prawda?Czy więc
BT Action
logika powinna znajdować się w / osobnych systemach (do których metod wskazuje mapa od pomysłu nr 1)? Następnie system sprawdzałby według mojegolong
„wskaźnika typu”, czy ten,Entity
dla którego BT jest aktualnie sprawdzany i który otrzymał polecenie wykonania określonej akcji (= metoda w systemie), jest w rzeczywistości dozwolony (= ma niezbędne komponenty). Ale jeśli nie (ponieważ na przykład twórca BT przeoczył określoną sytuację, w której niezbędny komponent może nie być dołączony do encji w czasie wykonywania), nic by się nie wydarzyło.
Pytania:
- Czy istnieją sprawdzone koncepcje tego rodzaju integracji?
- Co sądzisz o moich 3 punktach powyżej?
- Jakieś inne rzeczy, które przychodzą na myśl, również w odniesieniu do mojego projektu opartego na komponentach / elementach w ogóle?
źródło
Odpowiedzi:
Zapomnij o wskaźnikach funkcji i pomyśl o obiektach. Każdy węzeł w drzewie zachowań (BT od tego momentu) idealnie odpowiadałby jednemu obiektowi w kodzie. Obiekty te będą miały standardowy interfejs pozwalający na ułożenie ich jako drzewa i przechodzenie przez nie. Zestaw wskaźników funkcji jest odpowiedni dla zachowania, ale w ogóle nie odzwierciedla struktury twojego drzewa.
Oczekiwałbym, że podmioty będą miały jeden składnik BehaviorTree, który przechowuje odpowiednie dane dla BT tego podmiotu. Wykonanie BT jest wykonywane przez Komponent BT lub Podsystem BT w zależności od sposobu obsługi komponentów w systemie. Podobnie jak w przypadku prawie wszystkich komponentów, będą musieli odwoływać się do innych komponentów, aby wykonać zadanie, ale te inne komponenty nie będą musiały nic wiedzieć o BT.
Różne dostępne działania byłyby, na najprostszym poziomie, zakodowane w różnych obiektach węzła BT. Powinny one być w stanie zmusić odpowiedni podmiot do działania poprzez manipulowanie komponentami w razie potrzeby, np. dostęp do komponentu ruchu w celu przeniesienia.
źródło