Der Titel ist etwas verwirrend, aber ich kann mir nicht vorstellen, wie ich meine Frage in einem kurzen Satz erklären soll. Hier ist es also:
Immer wenn ich Game Engines schreibe, egal ob es sich um Physik / Kacheln usw. handelt, komme ich an den Punkt, an dem ich nicht sicher bin, wie ich die Dinge verwalten soll. Sollten Entitäten auf der Welt alleine handeln oder sollte es ein globales System geben, das sie verwaltet?
Hier ist ein einfaches Beispiel: Dinge bewegen. Sollte jedes Objekt die Welt um sich herum sehen (auf Kollisionen prüfen) und sich darauf basierend bewegen.
[Hinweis: Dies ist ein auf Kacheln basierendes Spiel, bei dem sich Objekte pro Kachel bewegen. Ich verwende also keine Physik, um von Kachel zu Kachel zu wechseln.]
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
if (world.getTile(location) != solid && world.objAtTile(location) == null)
{
Tweener.addTween(this, location);
}
}
}
Oder sollte die Bewegung jedes Objekts in der Welt gehandhabt werden, in der die Welt alles überprüft?
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
world.moveTo(location);
}
}
public class World
{
public void moveObject(GameObject obj, Vector2 location)
{
//called from object
if (getTile(location) != solid && objAtTile(location) == null)
{
Tweener.addTween(obj, location);
}
}
}
Für dieses Beispiel ist es nicht wirklich wichtig, aber ich kann sehen, dass ich später in Schwierigkeiten gerate. Danke im Voraus.
quelle
Actor
wissenworld
?Antworten:
Ich sehe, dass Ihre Beispiele in Java sind, aber Ihre Tags geben keine Sprache an. In C ++ lautet die Antwort weder - Sie sollten dafür keine Mitgliedsfunktion verwenden!
quelle
Es gibt keine einfache Antwort.
Wie bei den meisten Dingen in der Programmierung ist es ein Kompromiss. Wenn Sie einzelnen Objekten mehr Leistung verleihen, werden sie größer und damit langsamer, aber der Motor ist leichter zu verstehen und zu erweitern. Eine Mega-Klasse zu haben, die alles zusammen bewältigen kann, ist zwar schneller, aber auf Kosten einer Mega-Klasse. Das heißt, es wird allgemein als schlechte Form angesehen, supermassive Klassen zu machen.
Ich habe einige Artikel über komponenten- und datengesteuertes Design gelesen, in denen Sie eine einzige Klasse haben, die alle Objekte eines bestimmten Typs darstellt, deren Daten in Listen speichert und nur Indizes weitergibt, um Eigenschaften eines einzelnen Objekts abzurufen. Obwohl ich dies als eine realisierbare Art von Architektur ansehen kann, denke ich, dass sie eher mit dem ganzen Punkt der Objektorientierung zusammenhängt, der auch einen angemessenen Anteil an Kritik erhalten hat.
Ich persönlich empfehle, den Objekten mehr Kraft zu geben. In einer objektorientierten Sprache ist dies sinnvoller und (wie ich mir vorstellen kann) im Laufe der Zeit leichter zu verstehen und zu pflegen.
quelle
Ich aktualisiere meine Antwort, weil viele Dinge vor den Kommentaren nicht klar waren. Bitte entblößen Sie mich, während ich meine Gedanken erkläre.
Im Allgemeinen sind Kohäsion und Kopplung zwei Schlüsselaspekte, die bei jedem Entwurf berücksichtigt werden müssen . Wir alle wissen, dass wir eine hohe Kohäsion und eine geringe Kopplung benötigen, um ein wiederverwendbareres und erweiterbares Design zu erhalten.
Wenn die Welt also alles verwalten muss, bedeutet dies, dass sie einen geringen Zusammenhalt und eine enge Kopplung aufweist (weil sie alles wissen und tun muss). Dies ist jedoch auch dann der Fall, wenn eine Spieleinheit alles tun muss. Aktualisieren Sie seinen Standort, rendern Sie seine Textur usw. usw.
Was Sie wirklich interessiert, ist die Erstellung von Systemen, die sich auf einen Aspekt der Entität konzentrieren. Zum Beispiel könnte eine Spielentität eine Textur haben, aber ein Renderer wäre dafür verantwortlich, diese Textur auf dem Bildschirm zu rendern. Dem Renderer ist es egal, über welche anderen Eigenschaften die Entität verfügt.
Wenn man etwas weiter geht, ist eine Spieleinheit einfach eine Tüte mit Eigenschaften. Diese Eigenschaften werden von Systemen manipuliert, die sich auf bestimmte Eigenschaften konzentrieren. Und hier kommen komponentenbasierte Entitätssysteme (CBES) ins Spiel, bei denen Eigenschaften = Komponenten sind.
Insbesondere CBES mit Systemen (oder Subsystemen). Bei diesem Entwurf gibt es in der Regel einige Systeme, die sich auf bestimmte Komponenten einer Entität konzentrieren, ohne sich um die anderen Komponenten der Entität zu kümmern. Außerdem sind die Systeme nur mit den Informationen gekoppelt, die sie zur Verarbeitung dieser Komponenten benötigen.
Nehmen wir Ihr Beispiel. Da die Eingabe, wohin die Entität verschoben werden soll, auf dem Controller des Players basiert, hätten Sie wahrscheinlich ein PlayerControllerSystem. Dieses System würde neben vielen anderen Dingen die PositionComponent der Entität steuern. In diesem Fall müsste das PlayerControllerSystem die Ebene und die PositionComponent kennen. Wenn Sie sich später dazu entschließen, die Kollisionserkennung hinzuzufügen, würden Sie ein CollisionSystem erstellen, das erneut die Position der Entitäten verwendet, diesmal jedoch zur Berechnung der Begrenzungsrahmen (oder Sie könnten eine BoundingBoxComponent, Ihren Aufruf, haben). Tatsache ist, dass Sie das Verhalten einfach ein- oder ausschalten können (auch im laufenden Betrieb), indem Sie einfach Komponenten hinzufügen / entfernen. Mehr Verhalten bedeutet also, dass mehr Systeme die Komponenten einer Entität manipulieren, aber alle gehören zu einer genau definierten Klasse mit geringer Kopplung. Willst du Skripte? Fügen Sie eine ScriptComponent hinzu. BAM! Sie haben gerade Skriptfunktionen mit 2 Klassen hinzugefügt. Physik? Klang? Das selbe nochmal.
Der Grund, warum ich CBES mit SubSystems befürworte, ist, dass es perfekt OO und ein insgesamt leicht zu wartendes / erweiterbares System ist. Das Hinzufügen eines Verhaltens zu einer Entität ist so einfach wie die Entscheidung, welche Daten dieses Verhalten benötigt und welche Entitäten es benötigen.
Für weitere Informationen zu komponentenbasierten Entity-Systemen mit SubSystems gibt es eine hervorragende Reihe von Blog-Posts von T = Machine bei Entity Systems, die die Zukunft der MMOG-Entwicklung darstellen . Der Autor ging sogar so weit, ein Wiki zum Sammeln verschiedener Implementierungen mit dem Namen Entity Systems Project zu erstellen
Ein allgemeiner (und bekannter) Beitrag über komponentenbasierte Entitätssysteme im Allgemeinen ist die Evolve your hierarchy , die das System für Tony Hawk Pro erstellt hat.
Wenn Sie nach einer Bibliothek mit Beispielcode suchen, gehen Sie nicht weiter als bis zur Artemis- Bibliothek. Artemis ist hauptsächlich in Java, aber hier ist ein Port in C # (den ich derzeit in meinem XNA-Projekt verwende).
quelle
Normalerweise gehe ich mit einem Design um, bei dem Objekte sich selbst behandeln (dafür sind schließlich Methoden gedacht), aber die Basiswelt hat Listen aller Objekte und verwendet diese Listen, um sie zu koordinieren. Also so etwas wie:
quelle
Halten Sie es trocken, schüchtern und sagen Sie es dem anderen.
Es ist besser, die Welt zu bitten, Ihren Schauspieler zu bewegen, als die Welt zu fragen, ob Sie dorthin ziehen können, wo Sie hin möchten. Auf diese Weise können Sie den Pfadfindungsalgorithmus in der Weltklasse und dergleichen leicht ändern. Natürlich könnte man dies einfach einer Grundklasse für den Schauspieler überlassen, aber das ist die Richtung, die ich einschlagen würde, und der Grund dafür.
quelle
EDIT: Umgeschrieben aufgrund des Feedbacks, dass ich die Grenze für diese Antwort auf die ursprüngliche Frage nicht klar genug gezogen habe.
Ich möchte die Frage nach Möglichkeit etwas näher erläutern. Sollte die Logik, die auf ein Objekt einwirkt, intern oder extern zu diesem Objekt sein? Der letzte Teil des Beitrags erwähnt speziell die Langlebigkeit des Designs als Grundlage für die Beantwortung der Frage, um später Probleme zu vermeiden.
Meine einfache Antwort auf hoher Ebene besteht darin, die gesamte Logik, die auf ein Objekt wirkt, in diesem Objekt beizubehalten.
Sie brauchen nicht die Welt, um ein Objekt zu bewegen. Alles, was Sie brauchen, ist das zu bewegende Objekt und der Vektor, der den Ort darstellt, an den Sie sich bewegen möchten. Die Welt kann ins Spiel kommen, wenn ein Ziel ausgewählt wird oder wenn aufgrund einer Kollision eine Reaktion auf die Umgebung erforderlich ist, diese jedoch außerhalb des Beispiels liegen, an dem gearbeitet werden soll.
Um den zugrunde liegenden Teil der Frage anzusprechen und eine lange Lebensdauer des Designs zu erreichen, würde ich eine komponentenorientierte Architektur vorschlagen. Komponentenarchitekturen zerlegen ein Objekt in diskrete Datensätze und Funktionen (vorausgesetzt, Sie gehen mit meiner Antwort darüber, welche Zustände die Logik mit den Daten beibehalten sollen). Wenn Ihre Struktur wie CEntity-> CHuman-> CSoldier-> CPlayerCharacter aussieht, werden Sie immer auf Probleme stoßen, bei denen Sie eine Logik ändern müssen und je nachdem, wohin sie in diesem Baum geht (wie viele andere Arten von Menschen gibt es zum Beispiel?) Es kann weitreichende Auswirkungen auf mehrere Objekttypen haben.
Ein Komponentensystem verfügt stattdessen über eine Reihe von Schnittstellen, die definieren, woraus das CEntity-Objekt besteht, z. B. ICompRenderable, ICompMoveable, ICompHealth, ICompInventory usw. Wo Sie CCompMoveableHuman und möglicherweise einen CCompMoveableSoldier und CCompMoveablePlayer haben würden, um ihre individuellen Bewegungsmuster getrennt zu halten. Sagen wir also, der Soldat ist so verändert, dass er in Formationen läuft. Diese Änderung wirkt sich nur auf Entitäten aus, die mit dieser Komponente erstellt wurden.
Zusammenfassend schlage ich vor, dass Sie die Logik mit den Daten enthalten, für die die Logik gilt. Ich empfehle außerdem, Objekte in einzelne Komponenten zu zerlegen, um die Option "Wo lege ich das ab?" Zu reduzieren. Fragen und bieten Stabilität in die Zukunft mit einfacher Wartung und erweiterbar.
Hoffe das hilft.
quelle
Ich empfehle Ihnen, sich über komponentenbasierte Architekturen zu informieren. Es gibt eine ganze Reihe von Blog-Posts, Präsentationen und Aufzeichnungen darüber, die einen besseren Job machen können als ich es jemals könnte.
AltDevBlogADay hat einige Posts darüber, ein sehr guter ist diese Serie über Spieleentitäten: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-ia-retrospect/ Es gibt Mehrere Teile, die sich auf das Problem konzentrieren, das Sie lösen möchten.
quelle