Po przejrzeniu kilku wzorców projektowania gier, zdecydowałem się na Entity-Component-System (ES System) dla mojego silnika gry. Czytam artykuły (głównie T = Maszyna ) i przeglądam kod źródłowy i myślę, że mam dość, aby zacząć.
Jest tylko jeden podstawowy pomysł, z którym się zmagam. Jak postępować z grupami podmiotów, które są od siebie zależne?
Pozwól mi skorzystać z przykładu:
Załóżmy, że tworzę standardową strzelankę (myślę Jamestown ) i chcę zbudować „byt boski” z wieloma odrębnymi, ale połączonymi częściami. Podział może wyglądać mniej więcej tak:
- Korpus statku: ruch, renderowanie
- Cannon: Pozycja (zablokowana względem ciała statku), Śledzenie \ Ogień w bohaterze, Przyjmowanie obrażeń do momentu wyłączenia
- Rdzeń: Pozycja (zablokowana względem korpusu statku), Śledzenie \ Ogień w bohaterze, Przyjmowanie obrażeń do momentu wyłączenia, Wyłączanie (er ... niszczenie) wszystkich innych istot w grupie statków
Moim celem będzie coś, co zostanie zidentyfikowane (i zmanipulowane) jako odrębny element gry bez konieczności przepisywania podsystemu od podstaw za każdym razem, gdy chcę zbudować nowy element agregujący.
Jak wdrożyć tego rodzaju projekt w ES System?
- Czy wdrażam jakiś rodzaj relacji rodzic-dziecko (byty mogą mieć dzieci)? To wydaje się być sprzeczne z metodologią polegającą na tym, że Jednostki są tylko pustymi pojemnikami i sprawia, że wydaje się bardziej OOP.
- Czy zaimplementuję je jako osobne jednostki, z jakimś rodzajem łączenia Component (BossComponent) i powiązanego systemu (BossSubSystem)? Nie mogę przestać myśleć, że będzie to trudne do wdrożenia, ponieważ sposób komunikacji komponentów wydaje się być wielką pułapką na niedźwiedzie.
- Czy implementuję je jako jeden byt z kolekcją komponentów (ShipComponent, CannonComponents, CoreComponent)? Ten wydaje się odwracać intencję Systemu ES (tutaj komponenty wydają się zbyt podobne do jednostek o dużej wadze), ale wiem o tym, więc pomyślałem, że to tam przedstawię.
- Czy wdrażam je jako coś innego, o czym wspomniałem?
Wiem, że można to bardzo łatwo wdrożyć w OOP, ale wybiorę ES zamiast OOP, z którym będę się trzymał. Jeśli będę musiał zerwać z teorią czystego ES, aby wdrożyć ten projekt, zrobię to (nie tak, jakbym wcześniej nie musiał rezygnować z czystego projektu), ale wolałbym to zrobić ze względów wydajnościowych niż zacząć od złego projektu.
Aby uzyskać dodatkowy kredyt, pomyśl o tym samym projekcie, ale każda z „jednostek bossów” była faktycznie połączona z większą „jednostką BigBoss” złożoną z głównego korpusu, głównego rdzenia i 3 „podmiotów bossa”. Pozwoliłoby mi to znaleźć rozwiązanie dla co najmniej 3 wymiarów (dziadek-rodzic-dziecko) ... które powinno mi wystarczyć.
źródło
Odpowiedzi:
Gdybym był w takiej sytuacji, stworzyłbym każdą część szefa jako osobny byt. Te „pod-byty” obejmowałyby jakiś rodzaj
AttachmentPoint
lubParentEntity
komponent. Ten komponent zawierałby odniesienie do jednostki nadrzędnej i przesunięcie względem pozycji nadrzędnej. Podczas aktualizacji pozycji sprawdzają pozycję nadrzędną i stosują przesunięcie, aby wygenerować własną pozycję. Ponadto może sprawdzać, czy jednostka macierzysta nadal istnieje. Ponadto możesz miećSubEntity
komponent, który śledzi istnienie podelementów dla encji nadrzędnej. Pozwala to na robienie takich rzeczy, jak tylko narażenie rdzenia bossa na zniszczenie broni z tarczami.Obecnie używam
TargetEntity
komponentu w mojej grze, który służy do śledzenia wieżyczek i kiedy gobliny zamierzają odebrać surowiec. Może sprawdzić pozycję jednostki docelowej i odpowiednio zmienić jej zachowanie. Podmioty, które nie mają pozycji, nigdy nie są dodawane jako cel, więc nie ma się o co martwić. Jednak, gdy będziesz bardziej dogłębny, na przykład sprawdzając zdrowie jednostki nadrzędnej lub podrzędnej, tarczę, rezerwy mocy itp., Musisz upewnić się, że jednostka nadrzędna lub podrzędna faktycznie ma powiązany komponent.Utworzenie każdej części jako osobnej jednostki zachowuje elastyczność struktury encji / komponentów, umożliwiając dodawanie dodatkowych i różnych komponentów do każdej części szefa. Na przykład jedna część bossa może mieć komponent broni i komponent zdrowia, podczas gdy inna miałaby tarczę i komponent zdrowia.
Znalazłem kolejną dyskusję na ten temat tutaj . W którym użytkownicy dyskutują nad dodaniem wielu elementów tego samego typu do jednego elementu (co wydaje mi się złym pomysłem). Wydaje się, że jest to przydatna rozmowa, chociaż nie przeczytałem całej dyskusji.
źródło
Bez znajomości zbyt wielu szczegółów na temat istniejących systemów, sposobem, w jaki bym to modelował (i do pewnego stopnia w moim własnym systemie encji) jest posiadanie komponentu takiego jak AttachedTo (parentEntity). Każde dziecko może otrzymać składnik AttachedTo (boss).
System renderowania (lub cokolwiek innego) następnie pobiera elementy z komponentami: Position, AttachedTo itp. I tworzy odpowiednie hierarchie.
źródło
Jeśli chcesz, aby encja była reprezentowana tylko przez identyfikator, wówczas przechowywanie encji można wykonać za pomocą specjalnego komponentu. Możesz nazwać go CompositeComponent, a zawiera on listę identyfikatorów encji podrzędnych oraz interfejsy do dodawania / usuwania elementów podrzędnych z tej listy.
Oczywiście wszelkie komponenty, które zależą od pozycji itp., Będą musiały współpracować z tym, aby poprawnie umieścić jednostkę. Jak to zaimplementować, zależy nieco od tego, jak obecnie wdrażasz pozycjonowanie.
Nawiasem mówiąc, nie ma „czystej teorii ES” - popularne jest tworzenie jednostek z komponentów, ale precyzyjna metoda nie jest jeszcze znormalizowana.
źródło