Zaprojektowałem system encji dla FPS. Zasadniczo działa tak:
Mamy „światowy” obiekt o nazwie GameWorld. Zawiera tablicę GameObject, a także tablicę ComponentManager.
GameObject zawiera tablicę Component. Zapewnia również bardzo prosty mechanizm zdarzeń. Same komponenty mogą wysyłać zdarzenie do jednostki, które jest transmitowane do wszystkich komponentów.
Komponent jest w zasadzie czymś, co nadaje GameObject określone właściwości, a ponieważ GameObject jest tak naprawdę tylko ich pojemnikiem, wszystko, co ma związek z obiektem gry, dzieje się w Components. Przykłady obejmują ViewComponent, PhysicsComponent i LogicComponent. Jeśli potrzebna jest komunikacja między nimi, można to zrobić za pomocą zdarzeń.
ComponentManager to po prostu interfejs podobny do Component, a dla każdej klasy Component powinna zasadniczo istnieć jedna klasa ComponentManager. Ci menedżerowie komponentów są odpowiedzialni za tworzenie komponentów i inicjowanie ich właściwościami odczytanymi z czegoś takiego jak plik XML.
ComponentManager zajmuje się także masowymi aktualizacjami komponentów, takich jak PhysicsComponent, w którym będę korzystać z zewnętrznej biblioteki (która robi wszystko na świecie na raz).
W celu konfiguracji będę używać fabryki dla encji, które będą czytały plik XML lub skrypt, utworzą komponenty określone w pliku (który również dodaje odniesienie do niego w odpowiednim menedżerze komponentów dla masowych aktualizacji) i następnie wstrzyknij je do obiektu GameObject.
Teraz pojawia się mój problem: spróbuję użyć tego do gier wieloosobowych. Nie mam pojęcia, jak do tego podejść.
Po pierwsze: jakie podmioty powinny mieć klienci od samego początku? Powinienem zacząć od wyjaśnienia, w jaki sposób silnik dla jednego gracza określiłby, które podmioty stworzyć.
W edytorze poziomów możesz tworzyć „pędzle” i „byty”. Pędzle służą do takich rzeczy jak ściany, podłogi i sufity, w zasadzie proste kształty. Podmioty to GameObject, o którym ci mówiłem. Podczas tworzenia jednostek w edytorze poziomów można określić właściwości dla każdego z jego składników. Te właściwości są przekazywane bezpośrednio do konstruktora w skrypcie encji.
Po zapisaniu poziomu do załadowania silnik jest rozkładany na listę encji i powiązanych z nimi właściwości. Pędzle są konwertowane na „świat odradzający się”.
Gdy ładujesz ten poziom, po prostu inicjuje on wszystkie jednostki. Brzmi prosto, prawda?
Teraz w sieciach podmiotów napotykam wiele problemów. Po pierwsze, jakie podmioty powinny istnieć na kliencie od samego początku? Zakładając, że zarówno serwer, jak i klient mają plik poziomu, klient może równie dobrze zaimplementować wszystkie jednostki na poziomie, nawet jeśli są one tylko do celów reguł gry na serwerze.
Inną możliwością jest to, że klient inicjuje jednostkę, gdy tylko serwer wyśle o niej informacje, a to oznacza, że klient będzie miał tylko jednostki, których potrzebuje.
Kolejny problem dotyczy sposobu przesyłania informacji. Myślę, że serwer mógłby użyć kompresji delta, co oznacza, że wysyła nowe informacje tylko wtedy, gdy coś się zmienia, zamiast wysyłać migawkę do klienta w każdej ramce. Oznacza to jednak, że serwer musi śledzić to, co wie każdy klient.
I w końcu, jak należy wstrzykiwać sieci do silnika? Myślę o komponencie NetworkComponent, który jest wstrzykiwany do każdej encji, która ma być połączona w sieć. Ale w jaki sposób składnik sieciowy powinien wiedzieć, jakie zmienne podłączyć do sieci i jak uzyskać do nich dostęp, a na koniec, w jaki sposób odpowiedni składnik sieciowy na kliencie powinien wiedzieć, jak zmienić zmienne sieciowe?
Mam ogromne problemy z podejściem do tego. Byłbym bardzo wdzięczny, gdybyś pomógł mi w drodze. Jestem otwarty na wskazówki, jak ulepszyć projekt systemu komponentów, więc nie bój się tego sugerować.