Zmiany stanu jednostek lub komponentów

9

Mam problem z ustaleniem, jak radzić sobie z zarządzaniem stanem w moich podmiotach.

Nie mam problemów z zarządzaniem stanem gry, takimi jak pauza i menu, ponieważ nie są one traktowane jako system komponentów bytu; tylko ze stanem w jednostkach / komponentach.

Rysując z Orcs Must Die jako przykładu, mam moje elementy MainCharacter i Trap, które mają tylko takie elementy, jak PositionComponent, RenderComponent, PhysicsComponent.

Przy każdej aktualizacji Jednostka wywoła aktualizację swoich składników. Mam również ogólny menedżer zdarzeń EventManager z detektorami różnych typów zdarzeń.

Teraz muszę umieć pułapki: najpierw wybierz pułapkę i pozycję pułapki, a następnie umieść pułapkę.

Umieszczając pułapkę, powinna ona pojawić się przed MainCharacter, renderowana w inny sposób i podążać za nią. Po umieszczeniu powinien po prostu reagować na kolizje i być renderowany w normalny sposób.

Jak zwykle jest to obsługiwane w systemach opartych na komponentach?

(Ten przykład jest konkretny, ale może pomóc w ustaleniu ogólnego sposobu postępowania ze stanami jednostek).

GriffinHeart
źródło
1
Czy można dodawać i usuwać komponenty jednostek na podstawie zdarzeń wejściowych? Być może możesz zmienić komponenty pułapki, gdy zmienią się stany. Na przykład podczas umieszczania pułapki będzie ona mieć FollowComponent i RenderEffectComponnent. Po umieszczeniu usuwasz oba komponenty i dodajesz CollisionComponent. (Edytuj: Wyraźniej wyrażony przez Martina Sojkę)
Asakeron,
Tak, mogę, każde wejście jest tłumaczone z „HumanView” na zdarzenia w grze, które w większości są najpierw przetwarzane przez moją klasę GameLogic, która sprawdzi na przykład, czy MainCharacter ma wystarczająco dużo pieniędzy, aby umieścić pułapkę, w jaki sposób dzieje się po tym, co próbuję wymyślić.
GriffinHeart

Odpowiedzi:

6

Jedną z interesujących aplikacji systemu komponentów jest to, że można zmieniać komponenty jednostki w czasie wykonywania, jeśli zaprojektowano ją tak, aby była w stanie obsłużyć takie. Stan bytu staje się zatem sumą zarówno tego, które komponenty są mu przypisane, jak i tych, które posiadają.

Na przykład, możesz najpierw stworzyć pułapkę za pomocą BuildControllerComponent(regulującej reakcję na kontrolę gracza w fazie budowy), a PositionComponenti a RenderComponent. Ostatnie ma jedno pole danych, które rządzi zastosowanymi modułami cieniującymi pikseli, a jedno z nich nadaje wyglądowi „upiornego” pułapki. Zauważysz, że nie ma jeszcze przypisanych składników fizyki.

Po umieszczeniu pułapki komponenty są wymieniane. Nie BuildControllerComponentjest już potrzebny, więc zostaje usunięty. W RenderComponent„s shadery się zastąpić normalnego standardowego widoku pułapki. Wreszcie, PhysicsComponentpodobnie jak wszystko, co jest potrzebne do działania pułapki, są dodawane do encji.

W podejściu opartym na dziedziczeniu jest to równoważne z posiadaniem konstruktora dla ActiveTrapEntityklasy, który przyjmuje BuildTimeTrapEntityklasę jako argument, przy czym drugi służy do renderowania pułapki podczas jej budowania, a pierwszy służy do pułapki po jej umieszczeniu .

Martin Sojka
źródło
To jest sprytne.
Cypher
1
To dobra strategia stosowania stanu bytu. Nie rozwiązuje problemu śledzenia stanu każdej jednostki. Skąd wiesz, w jakim stanie jest obecnie jednostka?
MichaelHouse
@MartinSojka To jest prawie to, o czym myślałem po zadaniu pytania. Zastanawiałem się nad dodaniem BuildTrapProcess (coś, co jest aktualizowane w GameLogic), który będzie zarządzał aspektem wykonawczym zmiany składników, aby osiągnąć zmiany stanu potrzebne do zbudowania pułapki. Gdy zostanie wciśnięty przycisk budowy pułapki, logika gry utworzy Proces i go uruchomi. jakieś przemyślenia na temat tego podejścia?
GriffinHeart
@ Byte56: Ogólnie można wyszukiwać powiązane komponenty i ich wartości. W praktyce często musisz znać tylko odpowiedni podzbiór całego stanu, na przykład „Czy ten byt ma BuildControllerComponent?” lub „Jaka jest pozycja tego bytu, jak jest w nim zapisany PositionComponent, jeśli taki istnieje?” - te, które robisz, sprawdzając listę komponentów, które Cię interesują, i opcjonalnie sprawdzając (niektóre) ich wartości.
Martin Sojka
1
@GriffinHeart: Po prostu zaimplementuję wszystko, co jest potrzebne do „zbudowania” pułapki w systemie związanym z zarządzaniem BuildControllerComponents. Musi już przetwarzać zmiany punktu widzenia postaci (lub kamery) gracza oraz zdarzenia związane z naciśnięciem klawisza i myszy.
Martin Sojka
5

Nie podoba mi się pomysł, by podmioty wywoływały aktualizacje swoich komponentów (systemy powinny wykonywać tę pracę), a to doprowadzi do problemów z utrzymywaniem wzajemnej nieświadomości komponentów.

Możesz dodać dodatkowy komponent o nazwie „Stan”. Będą dostępne dla twoich systemów renderowania i kolizji. Składnik stanu to tylko flaga, która ma do dyspozycji wiele stanów. W opisanej sytuacji stanami byłyby Playi Build. Gdy system renderujący zobaczy, że jest w stanie Build, narysuje obiekt półprzezroczysty. Gdy system kolizji zobaczy Buildstan, nie będzie przetwarzał kolizji z odtwarzaczem.

Ale tak naprawdę, jeśli nie masz systemów i polegasz na komponentach, które wykonają całą pracę, napotkasz wiele problemów. Komponenty nie powinny wiedzieć o sobie i nie powinny przetwarzać.

MichaelHouse
źródło
To, co mówisz, jest sprzeczne, najpierw powinny być nieświadome (co zgadzam się), a następnie masz komponent, do którego inni mają dostęp. Możesz wyjaśnić? Trzymam komponenty odsprzężone przez system zdarzeń.
GriffinHeart
Mówię oba. Mówię, że powinni być nieświadomi i próbować dostosować moją odpowiedź do tego, jak myślę, że obchodzisz się z komponentami. Kiedy mówisz „Jednostka wywoła aktualizację na swoich komponentach”, daje mi to do zrozumienia, że ​​nie masz encji przetwarzających systemy. Usunąłem mylący język i po prostu powiedziałem, że to systemy. Mówiłem komponenty, ponieważ rozumiałem, że tak właśnie aktualizujesz.
MichaelHouse
Podoba mi się pomysł, StateComponentktóry może być konsumowany przez wiele systemów.
Cypher,
1
Uprzejme jest podanie uzasadnienia dla głosów negatywnych. Dzięki.
MichaelHouse
2
Z drugiej strony, twój sprzeciw wobec podejścia pytającego opiera się na założeniu, że cały projekt oparty na komponentach musi aktualizować komponenty z oddzielnych systemów (jak projekt systemu encji). Jest to jeden ze sposobów, ale na pewno nie jedyny, i nie ma powodu, aby zniechęcać do takiego podejścia w przypadku gry, która nie wymaga pętli aktualizacji komponentów optymalizujących pamięć podręczną.
Sean Middleditch,