Pracuję nad grą z architekturą opartą na komponentach. Jest Entity
właścicielem zestawu Component
instancji, z których każda ma zestaw Slot
instancji do przechowywania, wysyłania i odbierania wartości. Funkcje fabryczne, takie jak Player
tworzenie elementów z wymaganymi komponentami i połączeniami gniazd.
Próbuję ustalić najlepszy poziom szczegółowości dla komponentów. Na przykład teraz Position
, Velocity
i Acceleration
są wszystkie oddzielne elementy, połączone szeregowo. Velocity
i Acceleration
może być łatwo przepisany na jednolity Delta
komponent, lub Position
, Velocity
i Acceleration
może być łączony obok takich komponentów jak Friction
i Gravity
na monolityczny Physics
komponent.
Czy element powinien ponosić jak najmniejszą odpowiedzialność (kosztem wielu połączeń wzajemnych), czy też należy łączyć pokrewne elementy w elementy monolityczne (kosztem elastyczności)? Skłaniam się ku temu pierwszemu, ale przydałaby mi się druga opinia.
źródło
Odpowiedzi:
Istnieje granica między całkowitą ziarnistością, prowadzącą do braku marnotrawstwa kodu lub stanu podobnego do obiektu blob (dlatego preferowane są architektury komponentów), a użytecznością.
Oczywiście rzeczy mogą mieć
Position
, ale niekoniecznie są dynamiczne (więc dlaczegoVelocity
iAcceleration
?). Jednak coś z aVelocity
będzie ruchomym przedmiotem, więc sensowne jest takżeAcceleration
pogrupowanie.Czy będziesz miał przypadek, w którym będą potrzebne v i a , ale nie chcesz dla nich symulacji fizyki? Podobnie, czy będzie sens,
Gravity
jeśli nie są obiektami fizyki?tl; dr Group, co ma sens.
źródło
Entity
maPosition
pewne elementy, które sprawiają, żePosition
uczestniczą w fizyce, toEntity
jest de facto fizyczny. Myślę, że mogę po prostu dodać niektóre komponenty do logicznego grupowania i utrzymać wszystkie podstawowe komponenty w jednej odpowiedzialności. Więc dodając, powiedzmy,Movable
doEntity
będzie mieć taki sam skutek jak dodaniePosition
,Velocity
iAcceleration
.Aby uniknąć mikrozarządzania każdą zmienną, którą zasugerowałem, zaczynając od ciężkich, wybierz podziały wokół odpowiedzialności i zreformuj, gdy sytuacja przedstawia się logicznie. Możesz rozpocząć pierwsze projekty na papierze. W pewnym momencie te rażące podziały odpowiedzialności staną się budulcem twoich bytów.
Na przykład w pośpiechu masz grę. Gra dzieli się na środowisko + stan. Środowisko dzieli się na StaticWorld + MovingStuff. Stan dzieli się na AIControlled + PlayerControlled. Rażąca idea Obrażeń dzieli się na TakesDamage + GivesDamage.
I tak dalej.
Podobnie jak powszechna rada „Twórz gry, a nie silniki!” dla nowych praktyków polecam „Twórz gry, a nie rozbudowuj systemy!” ponieważ tylko dzięki osobistemu doświadczeniu z uruchomioną grą dowiesz się, czy w przyszłych pracach potrzebny będzie złożony system komponentów.
źródło
Sądzę, że łączę komponenty, które będą miały wiele interakcji. W twoim przypadku utrzymałbym pozycję w jednym składniku, a prędkość i przyspieszenie utrzymywałyby razem w składniku fizyki.
Ale to zależy w dużej mierze od tego, jakie są twoje funkcje gry (chyba że budujesz framework bez konkretnej gry).
źródło
Zdaję sobie sprawę, że to stare pytanie, ale może ktoś uzna tę odpowiedź za przydatną.
Wierzę, że
Systems
to pomoże ci zrozumieć, jak budować Komponenty. Systemy istnieją w architekturach, w których komponenty nie zawierają własnej logiki, oprócz prostych funkcji pobierających / ustawiających i funkcji pomocniczych. Systemy działają na jednostkach, które spełniają wymagania komponentu. Dlatego najlepiej jest oddzielić dane składowe w takim stopniu, w jakim ma to sens, aby dane te były przetwarzane bez innych danych.Na przykład możesz mieć
MovementSystem
aktualizację jego encjiPosition
na podstawie ichVelocity
. Może to dotyczyć prostych bytów w grze. Ale dla Gracza i Wrogów możesz chcieć ruchu,Acceleration
który jest przetwarzanyAcceleratedMovementSystem
. Ale na przeszkody możesz chciećFriction
. Terenu może mieć również tarcie, ale nie będzie miał składową prędkości. Ale co zGravity
? Po prostu dodaj go Gracz, Wróg i Przeszkoda i stwórz go,GravitySystem
aby go przetworzyć.Najważniejsze jest to, że im bardziej oddzielona swoje
Components
, tym bardziej rozciągliwyEntities
będzie podczas używaniaSystems
.Edycja: Sprawiono, że ostatnie oświadczenie stało się jaśniejsze.
Edycja: Ok, pracowałem nad własnym systemem i doszedłem do tego. Przykładem podziału pozycji i prędkości jest to, że manipulowanie prędkością powoduje zmianę pozycji za pomocą systemu Movement. W rezultacie „InputMovementSystem” nie potrzebuje pozycji, aby spowodować przejście odtwarzacza z danych wejściowych użytkownika, ponieważ MovementSystem odbierze zmiany prędkości, aby zastosować się do pozycji. To prawda, że nadal byłoby dobrze, gdyby je zebrać, ale to przykład, dlaczego tak nie jest.
Niedawno przeczytałem post na blogu, który powiedział coś takiego:
źródło