Dziedziczenie a kompozycja


16

Zarabiam pieniądze w C # Ogólnie w tym języku lubię rozdzielać wszystko do niebios za pomocą interfejsów. Pomogło mi to dobrze w kodzie korporacyjnym, ale przy pisaniu gier w C # mam tendencję do dziedziczenia, ponieważ jestem w stanie zdefiniować pewne domyślne zachowania dla klas podstawowych. Czuję się przy tym brudny, jakbym był nieposłuszny jakimś bogom architektury, który kiedyś powiedział „faworyzuj kompozycję zamiast dziedziczenia”. Wiem, że nie jest czarno-biały, ale wydaje mi się, że mógłbym użyć interfejsów z nieco większą pracą i osiągnąć mniej więcej to samo.

Co robią inni ludzie? Czy dziedziczenie jest właściwym podejściem do gier, czy powinienem dokonać refaktoryzacji w niektórych interfejsach?


1
Interfejsy też nie są kompozycjami, więc nie jest jasne, o co pytasz.

Chciałbym tylko wspomnieć, że ponieważ pracujesz z C #, miałbyś trudności z wyborem dziedziczenia, ponieważ C # nie obsługuje prawdziwego wielokrotnego dziedziczenia. Używanie metody wielu interfejsów jest w porządku, dopóki nie przejdziesz do zakresu interfejsu 4-5 i będziesz musiał wyciąć / wkleić ponad 25 linii kodu między każdą klasą, która ma tę samą implementację. Istnieje kilka rund, ale są one równie brzydkie, ponieważ język nie zapewnia bezpośredniego wsparcia.
NtscCobalt

Odpowiedzi:


23

Dziedziczenie w grach jest w rzeczywistości jedną z najgorszych rzeczy, które możesz zrobić - w szczególności w odniesieniu do bytów. Przeczytaj to, dlaczego. Kompozycja zamiast dziedziczenia zabiera Cię w gry. Jeśli chodzi o inne obszary silnika, tak naprawdę nie ma to znaczenia. Załóżmy na przykład, że wykonujesz połączenie z zewnętrzną usługą sieciową, a następnie możesz odziedziczyć jedną rodzajową usługę np. HTTPService i SocketService - bardzo podobnie jak w aplikacjach korporacyjnych, do których jesteś przyzwyczajony.

Chyba, że gra jest bardzo prosta, to będzie chciał użyć jednostki (CBE) architekturę modułową. Ogólna idea jest taka, że ​​w przypadku encji przyczyną tak powszechnego tworzenia, a nie dziedziczenia jest to, że nie można wiedzieć do czasu uruchomienia, jakie możliwości będzie miała dana jednostka. Weźmy na przykład statek gracza w kosmicznej strzelance. Do pewnego momentu podczas gry nie wiesz, jaką broń, zbroję, systemy (tj. Komponenty) ten gracz będzie zbierał, kupował, sprzedawał, gubił, zniszczył itp. Tak więc jedynym realistycznym sposobem modelowania tego jest poprzez kompozycję obiektu. Zaletą tego scenariusza jest to, że możesz mieć w pełni konfigurowalnych wrogów zbudowanych w ten sam sposób, a nie wrogów, którzy są zawsze tacy sami za każdym razem, gdy widzisz tego typu wroga. Tak więc w przypadku CBE możesz zobaczyć marsjańskiego frachtowca i pomyśleć: „Ach, ma tylko małe lasery, zdejmę go”, i zwykle byłoby to prawdą, ale kiedy nagle znajdziesz się w zasięgu, zdajesz sobie sprawę, że ma duży tyłek pistolet czasoprzestrzenny. Niespodzianka niespodzianka!

Komponentizacja usuwa niejawne sprzężenie logiki, i to jest DOBRE.


Dzięki za radę kolego :) Miło wiedzieć, że nie słyszę głosów!
Peter Krótki

1
+1 Dzięki za artykuł, zamierzałem to zrobić w mojej grze od dłuższego czasu
John McDonald

3
Należy zauważyć, że ze względu na dużą wzajemną zależność bytów gry dziedziczenie często komplikuje rzeczy i sprawia, że ​​łatwość konserwacji i rozbudowy jest uciążliwym zadaniem. Systemy składowe ładnie radzą sobie z tym problemem, a druga dodatkowa korzyść jest wymieniona w powyższej odpowiedzi;)
James

Należy również zauważyć, że „ale kiedy nagle znajdziesz się w zasięgu, zdajesz sobie sprawę, że ma on duży tunel czasoprzestrzenny. Niespodzianka niespodzianka!” jest zły projekt gry: D
Jonathan Connell

1
Niespodzianki są zabawne, ale niespodzianki, które oznaczają śmierć bez ostrzeżenia, jak statek niskiego poziomu, który może cię OHKO, są po prostu frustrujące;) Oczywiście to może nie być to, co miałeś na myśli w swojej odpowiedzi. Poza tym gra to znacznie więcej niż sama gra.
Jonathan Connell,

3

Dla tych, którzy mówią po niemiecku, interesująca książka: http://www.amazon.com/Architektur-Kerns-einer-Game-Engine-Implementierung/dp/3639324471/ref=sr_1_1?ie=UTF8&qid=1314875533&sr=8-1

Bliższe spojrzenie na to, kiedy i dlaczego wykorzystać którą architekturę można znaleźć tutaj: /programming/1901251/component-based-game-engine-design

Dla siebie decyduję o mojej architekturze w zależności od wielkości projektu i możliwości rozszerzenia lub ponownego użycia kodu. Po co inwestować godziny w architekturę mikroprojektów, w których nie ma szans na ponowne użycie kodu? W tym samym czasie możesz zakończyć projekt.

Kompozycja a komponenty Komponenty to fajne, fantazyjne rzeczy, ale w większości projektów / architektur kompozycja również to robi (bez narzutu na komponenty). To zależy od tego, co twój system komponentów może zapewnić, czego kompozycja nie może.


Weźmy na przykład statek gracza w kosmicznej strzelance. Do pewnego momentu podczas gry nie wiesz, jaką broń, zbroję, systemy (tj. Komponenty) ten gracz będzie zbierał, kupował, sprzedawał, gubił, zniszczył itp. Tak więc jedynym realistycznym sposobem modelowania tego jest poprzez kompozycję obiektu.

wszystko to było dawno możliwe także bez komponentów


-1, składniki są formą kompozycji.

Cóż, forma, ale nie taka sama, ponieważ zapewniają różne funkcje. (Więc nie rozumiem twojego komentarza i -1)
idefix

1
Kiedy mówisz „kompozycja vs komponenty”, nie jest jasne, co porównujesz, ponieważ komponenty kompozycją. Czy masz na myśli komponenty dynamiczne vs. komponenty statyczne? Któryś z tych zestawień typów nie był ani rodzinny, ani strukturalnie? Co to jest „koszty ogólne oparte na komponentach”? W układach elementów statycznych (i wielu dynamicznych) narzut jest prawie zerowy.

Hm, ciekawe punkty. Masz coś przeciwko bardziej szczegółowej dyskusji? Jeśli nie, chciałbym przesłać ci mój adres e-mail na innej platformie.
idefix
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.