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).
źródło
Odpowiedzi:
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), aPositionComponent
i aRenderComponent
. 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
BuildControllerComponent
jest już potrzebny, więc zostaje usunięty. WRenderComponent
„s shadery się zastąpić normalnego standardowego widoku pułapki. Wreszcie,PhysicsComponent
podobnie 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
ActiveTrapEntity
klasy, który przyjmujeBuildTimeTrapEntity
klasę 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 .źródło
BuildControllerComponent
?” lub „Jaka jest pozycja tego bytu, jak jest w nim zapisanyPositionComponent
, 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.BuildControllerComponent
s. Musi już przetwarzać zmiany punktu widzenia postaci (lub kamery) gracza oraz zdarzenia związane z naciśnięciem klawisza i myszy.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
Play
iBuild
. Gdy system renderujący zobaczy, że jest w stanieBuild
, narysuje obiekt półprzezroczysty. Gdy system kolizji zobaczyBuild
stan, 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ć.
źródło
StateComponent
który może być konsumowany przez wiele systemów.