Struktura jednostek gry RTS

18

Chcę stworzyć wiele różnych jednostek bez konieczności programowania rzeczy takich jak moveTo i Attack więcej niż raz

Z mojego punktu widzenia mogę to zrobić na 2 sposoby.

  1. Pojedyncza ogólna klasa Unit z flagami, która określa, co może / nie może zrobić (następnie tworzy instancje w tablicy statycznej i pobiera je w razie potrzeby)
  2. Klasa abstrakcyjna jednostki z abstrakcyjnymi metodami dla akcji specyficznych dla Jednostki, takich jak (Atak, Żniwa, Patrol), które następnie muszą zostać zaimplementowane w podklasach , nawet jeśli jednostka nie jest w stanie niczego zebrać.

pierwszy sposób na zrobienie tego wydaje się najprostszy, ale w końcu większość jednostek nie byłaby używana.

drugi sposób może również działać. Ale jeśli zdecyduję się na dwie różne jednostki, które mogą zbierać zasoby, będę miał dokładnie ten sam kod w dwóch różnych klasach, co nie wydaje się być właściwym sposobem na zrobienie tego.

Czy to jest właściwe podejście do tego problemu?
W grze takiej jak obszar, każda jednostka ma, jak przypuszczam, jakąś Listę Akcji / Rozkazów, naprawdę chciałbym wiedzieć, jak osiągnąć coś podobnego do tego, gdzie mogę po prostu kodować każdą Akcję / Rozkaz raz, i następnie daj je wszystkim jednostkom, które potrzebują wspomnianej Akcji.

Jeśli jestem niejasny (wysoce prawdopodobne) lub potrzebujesz więcej informacji na temat tego, czego dokładnie szukam, po prostu zapytaj mnie w komentarzu.

Daniel Holst
źródło

Odpowiedzi:

25

Powszechnym podejściem jest podejście oparte na komponentach, w którym „jednostka” klasy podstawowej po prostu implementuje najbardziej podstawowe aspekty wspólne dla wszystkich jednostek, a następnie każda jednostka ma listę wielu obiektów-komponentów, które mówią, co może zrobić, i jak to robi

Na przykład, zbiornik może mieć składniki Mobile, Destructible, Attacker, nieruchomym wieżyczka tylko Destructible, Attackera kombajn Mobile, Destructible, Harvester. Klasy te zawierałyby wówczas cały kod potrzebny do wdrożenia tych zachowań. Interakcje między komponentami ( Attackermogą tylko uszkodzić to, co jest Destructible) można zrealizować, sprawdzając komponent, czy druga jednostka ma wymagany komponent, a następnie bezpośrednio wchodząc w interakcje z tym komponentem.

Zaletą klasycznego dziedziczenia klasowego jest to, że można łatwo łączyć umiejętności. Na przykład, jeśli chcesz mieć kombajn, który może również atakować, transportować piechotę i latać, wystarczy dodać niezbędne komponenty. Możesz także łatwo dodawać i usuwać nowe funkcje w postaci nowych komponentów bez potrzeby rozszerzania podstawowej klasy jednostek.

Unity wspiera Cię w takiej architekturze, ponieważ cały silnik jest już oparty na komponentach. Tak więc komponenty logiczne do gry można dodawać w postaci skryptów.

Philipp
źródło
Więc w jedności, czy w takim razie wyłączałbym i włączał komponenty w razie potrzeby ?.
Daniel Holst
@DanielHolst Nie, należy je dodawać i usuwać w razie potrzeby. Możesz to zrobić w edytorze Unity lub za pomocą skryptów za pomocą gameObject.AddComponenti gameObject.RemoveComponent.
Philipp
no dobrze, ale powiedz o akcji / porządku „moveTo”. skąd jednostka będzie wiedziała, kiedy zamówienie zostanie zrealizowane? i jak mam kolejkować zamówienia?
Daniel Holst
2
@DanielHolst Myślę, że coś źle zrozumiałeś. Te Movingśrodki składnik „to urządzenie jest na ogół zdolna do przemieszczania”. Komponent jest na stałe do niego przymocowany, niezależnie od tego, czy jednostka się porusza, czy nie. To nie znaczy, że teraz się porusza . Chociaż można to również zrobić w ten sposób, dodając MoveOrderdo niego komponent i usuwając go z jednostki, gdy zamówienie zostanie zrealizowane lub anulowane.
Philipp
1
@DanielHolst Teraz dryfujesz w kierunku jednostki AI, która jest zupełnie inną puszką robaków. Możliwym podejściem byłoby posiadanie biblioteki składników AIScript, które albo zakładają, że pewne składniki są obecne, albo zmieniają swoje zachowanie w zależności od tego, jakie elementy ma jednostka. Ale to naprawdę zbyt skomplikowany temat, aby poradzić sobie w komentarzu.
Philipp
4

Wiele gier korzysta z systemu opartego na komponentach dla bytów, w którym wiązka zachowań i umiejętności może być dodana do bardziej ogólnego typu jednostki, a nie kodowana jako część klasy bytu (lub równoważnego).

Ross Taylor-Turner
źródło
czy byłoby to niezwykle trudne do wdrożenia?
Daniel Holst
Takie wzorce służą do ogólnego ułatwienia implementacji. Jeśli nie możesz zdecydować, jakie podejście wybrać, dobrym pomysłem jest zacząć tak prosto, jak to możliwe, i poszerzać swój wybór, zwiększając funkcjonalność. Po dokładniejszym zapoznaniu się z problemem możesz albo przebudować, albo przepisać podejście, które lepiej pasuje do Twojej sytuacji.
Ross Taylor-Turner
1
@DanielHolst Zauważyłem, że twoje pytanie ma Unityflagę. Unity ma już wbudowany system komponentów i zdecydowanie preferuje kompozycję zamiast dziedziczenia . Jedną z prostych metod byłoby utworzenie MonoBehaviourdla każdego rodzaju akcji, a następnie dołączenie do każdego typu jednostki prefabrykuj działania, które jest ona w stanie wykonać (dostosowując instancje akcji za pomocą szczegółów poszczególnych rodzajów, takich jak wartości obrażeń i koszty). Dzięki temu tworzenie jednostek zależy od danych, dzięki czemu można łatwo tworzyć wiele niestandardowych typów jednostek.
DMGregory
@DanielHolst To zależy od twojej definicji „niezwykle trudny”. Moja odpowiedź zawiera bardziej szczegółowe informacje na temat tego, jak można to zaimplementować.
Philipp