Ist das Entity Component System-Architekturobjekt per Definition ausgerichtet?


20

Ist die Entity Component System-Architektur per Definition objektorientiert? Es scheint mir prozeduraler oder funktionaler zu sein. Meiner Meinung nach hindert es Sie nicht daran, es in einer OO-Sprache zu implementieren, aber es wäre nicht idiomatisch, dies auf eine konsequente OO-Art und Weise zu tun.

ECS scheint Daten (E & C) vom Verhalten (S) zu trennen. Als Beweis :

Die Idee ist, dass keine Spielmethoden in die Entität eingebettet sind.

Und :

Die Komponente besteht aus einem minimalen Datensatz, der für einen bestimmten Zweck benötigt wird

Systeme sind Einzweckfunktionen, die eine Reihe von Entitäten mit einer bestimmten Komponente enthalten


Ich denke, dies ist nicht objektorientiert, da ein großer Teil der Objektorientierung darin besteht, Ihre Daten und Ihr Verhalten miteinander zu kombinieren. Als Beweis :

Im Gegensatz dazu ermutigt der objektorientierte Ansatz den Programmierer, Daten an Stellen zu platzieren, auf die der Rest des Programms nicht direkt zugreifen kann. Stattdessen wird auf die Daten zugegriffen, indem speziell geschriebene Funktionen, üblicherweise Methoden genannt, aufgerufen werden, die mit den Daten gebündelt werden.

Bei ECS geht es anscheinend nur darum, Ihre Daten von Ihrem Verhalten zu trennen.

Antworten:


21

Einführung


Entity-Component-Systeme sind eine objektorientierte Architekturtechnik.

Es besteht kein allgemeiner Konsens darüber, was der Begriff bedeutet, genau wie bei der objektorientierten Programmierung. Es ist jedoch klar, dass Entity-Component-Systeme speziell als architektonische Alternative zur Vererbung gedacht sind . Vererbungshierarchien sind ein natürlicher Ausdruck dafür, was ein Objekt ist . Bei bestimmten Arten von Software (z. B. Spielen) möchten Sie jedoch eher ausdrücken, was ein Objekt tut .

Es handelt sich um ein anderes Objektmodell als das „Klassen- und Vererbungsmodell“, an das Sie wahrscheinlich aus der Arbeit in C ++ oder Java gewöhnt sind. Entitäten sind genauso aussagekräftig wie Klassen, genau wie Prototypen wie in JavaScript oder Self - alle diese Systeme können in Bezug auf einander implementiert werden.

 

Beispiele


Angenommen, dies Playerist eine Entität mit Position, Velocityund KeyboardControlledKomponenten, die die offensichtlichen Dinge tun.

entity Player:
  Position
  Velocity
  KeyboardControlled

Wir wissen, Positiondass davon Velocityund Velocityvon etwas betroffen sein muss KeyboardControlled. Die Frage ist, wie wir diese Effekte modellieren möchten.

 

Entitäten, Komponenten und Systeme


Angenommen, Komponenten haben keine Referenzen zueinander. ein externes PhysicsSystem durchläuft alle VelocityKomponenten und aktualisiert die Positionder entsprechenden Entität; Ein InputSystem durchläuft alle KeyboardControlledKomponenten und aktualisiert die Velocity.

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

Dies erfüllt die Kriterien:

  • Keine Spiel- / Geschäftslogik wird von der Entität ausgedrückt.

  • Komponenten speichern Daten, die das Verhalten beschreiben.

Die Systeme sind jetzt für die Behandlung von Ereignissen und die Umsetzung des von den Komponenten beschriebenen Verhaltens verantwortlich. Sie sind auch für die Handhabung von Interaktionen zwischen Entitäten verantwortlich, z. B. für Kollisionen.

 

Einheiten und Komponenten


Allerdings wird angenommen , dass Komponenten zu tun haben Referenzen zueinander. Jetzt ist die Entität einfach ein Konstruktor, der einige Komponenten erstellt, sie zusammenfügt und ihre Lebensdauer verwaltet:

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

Die Entität kann jetzt Eingabe- und Aktualisierungsereignisse direkt an ihre Komponenten senden. Velocitywürde auf Aktualisierungen und KeyboardControlledauf Eingaben reagieren. Dies erfüllt immer noch unsere Kriterien:

  • Die Entität ist ein "dummer" Container, der Ereignisse nur an Komponenten weiterleitet.

  • Jede Komponente führt ein eigenes Verhalten aus.

Hier werden Komponentenwechselwirkungen explizit und nicht von außen von einem System auferlegt. Die Daten, die ein Verhalten beschreiben (wie hoch ist die Geschwindigkeit?) Und der Code, der es ausführt (wie hoch ist die Geschwindigkeit?), Sind gekoppelt, jedoch auf natürliche Weise. Die Daten können als Parameter für das Verhalten angesehen werden. Und einige Komponenten wirken überhaupt nicht - a Positionist das Verhalten , an einem Ort zu sein .

Interaktionen können auf der Ebene der Entität ("wenn eine Playermit einer Enemy... kollidiert ") oder auf der Ebene einzelner Komponenten ("wenn eine Entität Lifemit einer Entität mit Strength... kollidiert ") behandelt werden.

 

Komponenten


Was ist der Grund für die Existenz des Unternehmens? Wenn es sich lediglich um einen Konstruktor handelt, können wir ihn durch eine Funktion ersetzen, die eine Reihe von Komponenten zurückgibt. Wenn wir später Entitäten nach ihrem Typ abfragen möchten, können wir auch eine TagKomponente haben, mit der wir genau das tun können:

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • Entitäten sind so dumm wie nur möglich - sie sind nur Sätze von Komponenten.

  • Komponenten reagieren wie bisher direkt auf Ereignisse.

Interaktionen müssen jetzt durch abstrakte Abfragen behandelt werden, wodurch Ereignisse vollständig von Entitätstypen entkoppelt werden. Es sind nicht mehr Entitätstypen abzufragen - beliebige TagDaten werden wahrscheinlich besser zum Debuggen verwendet als die Spielelogik.

 

Fazit


Entitäten sind keine Funktionen, Regeln, Akteure oder Datenflusskombinatoren. Sie sind Substantive, die konkrete Phänomene modellieren - mit anderen Worten, sie sind Objekte. Wikipedia sagt: Entity-Component-Systeme sind ein Software-Architekturmuster zur Modellierung allgemeiner Objekte.


2
Die Hauptalternative zu klassenbasiertem OO, prototypbasiertem OO, scheint ebenfalls Daten und Verhalten zu koppeln. Tatsächlich scheint es sich von ECS genauso zu unterscheiden wie klassenbasierte OO. Könnten Sie also erläutern, was Sie mit OO meinen?

Sind Sie nicht einverstanden mit dem Snippet des OO Wikipedia-Artikels, den ich zitiert habe?
Daniel Kaplan

@tieTYT: Das Wikipedia-Zitat handelt von Einkapselung und dem Verbergen von Informationen. Ich glaube nicht, dass es Beweise dafür gibt, dass eine Daten-Verhaltens-Kopplung erforderlich ist, nur, dass sie häufig vorkommt.
Jon Purdy

@delnan: Ich meine nichts mit OO. Objektorientiertes Programmieren ist für mich genau das, was es verspricht: Programmieren mit „Objekten“ (im Gegensatz zu Funktionen, Regeln, Akteuren, Datenflusskombinatoren usw.), bei denen die jeweilige Definition des Objekts durch die Implementierung definiert wird.
Jon Purdy

1
@tieTYT: Ich habe nur Implementierungen beschrieben, die ich in der freien Natur gesehen habe, um zu vermitteln, dass es ein weiter Begriff ist - nicht im Widerspruch zu der Wikipedia-Beschreibung, aber sicherlich weiter als diese.
Jon Purdy

20

NEIN. Und ich bin überrascht, wie viele Leute anders abgestimmt haben!

Paradigma

Es ist datenorientierte aka Datengetriebene , weil wir über die reden Architektur und nicht die Sprache es in geschrieben. Architekturen sind Realisierungen von Arten oder Programmierparadigmen , die in der Regel unadvisably um in einer bestimmten Sprache gearbeitet werden.


Funktionell?

Ihr Vergleich zur funktionalen / prozeduralen Programmierung ist ein relevanter und aussagekräftiger Vergleich. Beachten Sie jedoch, dass sich eine "funktionale" Sprache vom "prozeduralen" Paradigma unterscheidet . Und Sie können ein ECS in einer funktionalen Sprache wie Haskell implementieren , was die Leute getan haben.


Wo Zusammenhalt passiert

Ihre Beobachtung ist relevant und genau richtig :

"... [ECS] hindert Sie nicht daran, es in einer OO-Sprache zu implementieren, aber es wäre nicht idiomatisch, dies auf eine konsequente OO-Weise zu tun."


ECS / ES ist nicht EC / CE

Es gibt einen Unterschied zwischen den komponentenbasierten Architekturen "Entity-Component" und "Entity-Component-System". Da dies ein sich entwickelndes Entwurfsmuster ist, habe ich gesehen, dass diese Definitionen synonym verwendet werden. "EC" - oder "CE" - oder "Entity-Component" -Architekturen ordnen Verhalten in Komponenten ein , wohingegen "ES" - oder "ECS" -Architekturen Verhalten in Systemen ordnen . Hier sind einige ECS-Artikel, die beide irreführende Nomenklaturen verwenden, aber die allgemeine Vorstellung vermitteln:

Wenn Sie versuchen, diese Begriffe im Jahr 2015 zu verstehen, stellen Sie sicher, dass der Verweis auf "Entity Component System" nicht "Entity-Component-Architektur" bedeutet.


1
Das ist die richtige Antwort. ECS passt nicht sehr gut zu OOP-Paradigmen, da es bei ECS um die Trennung von Daten und Verhalten geht, während bei OOP das Gegenteil der Fall ist.
Nax 'vi-vim-nvim',

"während OOP das Gegenteil ist" Es gibt keine akzeptierte Definition dessen, worum es bei OOP geht, es sei denn, nutzlose akademische Definitionen wie SmallTalks, die in der Praxis niemals verwendet werden.
Jean-Michaël Celerier

10

Entity Component Systems (ECSs) können je nach Systemdefinition in OOP- oder funktionaler Weise programmiert werden.

OOP Weg:

Ich habe an Spielen gearbeitet, in denen eine Entität ein Objekt war, das aus verschiedenen Komponenten bestand. Die Entität verfügt über eine Aktualisierungsfunktion, die das vorhandene Objekt ändert, indem sie nacheinander update für alle ihre Komponenten aufruft. Dies ist eindeutig OOP im Stil - das Verhalten ist mit Daten verknüpft und die Daten sind veränderlich. Entitäten sind Objekte mit Konstruktoren / Destruktoren / Aktualisierungen.

Mehr funktionale weg:

Eine Alternative besteht darin, dass die Entität Daten ohne Methoden ist. Diese Entität kann für sich existieren oder einfach eine ID sein, die mit verschiedenen Komponenten verknüpft ist. Auf diese Weise ist es möglich (aber nicht allgemein üblich), voll funktionsfähig zu sein und unveränderliche Entitäten und reine Systeme zu haben, die neue Komponentenzustände erzeugen.

Es scheint (aus eigener Erfahrung), dass der letztere Weg aus gutem Grund mehr Bodenhaftung gewinnt. Die Trennung von Entitätsdaten und Verhalten führt zu flexiblerem und wiederverwendbarem Code (imo). Insbesondere die Verwendung von Systemen zum Aktualisieren von Komponenten / Entitäten in Stapeln kann leistungsfähiger sein und die Komplexität von Inter-Entity-Messaging, die viele OOP-ECS-Systeme plagt, vollständig vermeiden.

TLDR: Sie können es auf beide Arten tun, aber ich würde argumentieren, dass die Vorteile guter Entitätskomponentensysteme von ihrer funktionaleren Natur herrühren.


Mehr Zugkraft, zumal der springende Punkt bei den Komponenten darin bestand, sich von hartnäckigen OOP-Hierarchien zu lösen, eine gute Beschreibung des Nutzens.
Patrick Hughes

2

Datenorientierte Entität Komponentensysteme können mit objektorientierten Paradigmen koexistieren: - Komponentensysteme eignen sich für Polymorphismus. - Komponenten können sowohl POD (einfache alte Daten) als auch ALSO-Objekte (mit einer Klasse und Methoden) sein, und das Ganze ist immer noch "datenorientiert", vorausgesetzt, dass Komponentenklassenmethoden nur Daten manipulieren, die dem lokalen Objekt gehören.

Wenn Sie diesen Pfad auswählen, wird empfohlen, die Verwendung virtueller Methoden zu vermeiden, da Ihre Komponente bei Vorhandensein dieser Methoden nicht mehr nur aus Komponentendaten besteht und der Aufruf dieser Methoden mehr kostet - dies ist keine COM. Halten Sie Ihre Komponentenklassen in der Regel frei von externen Verweisen.

Ein Beispiel wäre vec2 oder vec3, ein Datencontainer mit einigen Methoden zum Berühren dieser Daten und nichts weiter.


2
Dieser Beitrag ist ziemlich schwer zu lesen (Textwand). Hätten Sie etwas dagegen bearbeiten sie in eine bessere Form ing? Auch würde es helfen , wenn Sie den Lesern erklären , warum sie Blog - Artikel nützlich und relevant für die Frage verknüpft finden gefragt ...
gnat

... für den Fall, dass Sie in irgendeiner Weise mit diesem Blog verwandt sind (oder?), wäre es auch wünschenswert, die Zugehörigkeit offenzulegen
gnat

Ja, das ist mein Blog. Ich bin eng mit meinem öffentlichen Blog verbunden, in dem Details eines objektorientierten Entitätskomponentensystems auf der Grundlage datenorientierter Gestaltungsprinzipien veröffentlicht werden. Ich halte dies für relevant und möglicherweise nützlich, habe jedoch den Link zu entfernt entfernen Sie alle Vorurteile.
Homer

2

Ich halte ECS für grundlegend anders als OOP und neige dazu, es so zu sehen, wie Sie es tun, als funktionaler oder vor allem prozeduraler Natur mit einer sehr deutlichen Trennung von Daten und Funktionalität. Es gibt auch einen Anschein für eine Programmierung, die sich mit zentralen Datenbanken befasst. Natürlich bin ich die schlechteste Person, wenn es um formale Definitionen geht. Es geht mir nur darum, wie die Dinge sind und nicht wie sie konzeptionell definiert sind.

Ich gehe von einer Art ECS aus, bei der Komponenten Datenfelder aggregieren und sie öffentlich / global zugänglich machen, Entitäten Komponenten aggregieren und Systeme Funktionen / Verhalten für diese Daten bereitstellen. Das führt zu radikal schwierigen architektonischen Merkmalen, die wir normalerweise als objektorientierte Codebasis bezeichnen würden.

Und natürlich verschwimmen die Grenzen in der Art und Weise, wie Menschen ein ECS entwerfen / implementieren, und es gibt Debatten darüber, was genau ein ECS überhaupt ausmacht. Solche Grenzen verschwimmen jedoch auch im Code, der in einer von uns als funktional oder prozedural bezeichneten Sprache geschrieben ist. Bei all dieser Unschärfe scheint mir die grundlegende Konstante eines ECS mit einer Trennung von Daten und Funktionalität der funktionalen oder prozeduralen Programmierung viel näher zu sein als OOP.

Ich Einer der Hauptgründe , glaube nicht , ist es hilfreich, ECS zu prüfen , in einer Klasse von OOP zu gehören , ist , dass die meisten der SE Praktiken mit OOP assoziiert drehen sich um öffentliche Schnittstelle Stabilität, mit öffentlichen Schnittstellen Modellierungsfunktionen , keine Daten. Die Grundidee ist, dass der Großteil der öffentlichen Abhängigkeiten zu abstrakten Funktionen fließt, nicht zu konkreten Daten. Aus diesem Grund macht es OOP in der Regel sehr kostspielig, grundlegende Design-Verhaltensweisen zu ändern, während es sehr kostengünstig ist, konkrete Details (wie Daten und Code, die zur Implementierung der Funktionalität erforderlich sind) zu ändern.

In dieser Hinsicht unterscheidet sich ECS grundlegend von der Kopplung, da der Großteil der öffentlichen Abhängigkeiten zu konkreten Daten fließt: von Systemen zu Komponenten. Infolgedessen dreht sich jede mit ECS verbundene SE-Praxis um Datenstabilität , da die am häufigsten verwendeten öffentlichen Schnittstellen (Komponenten) eigentlich nur Daten sind.

Aus diesem Grund ist es mit einem ECS sehr einfach, eine DirectX-Engine durch eine OpenGL-Rendering-Engine zu ersetzen, auch wenn beide mit völlig unterschiedlichen Funktionen implementiert sind und nicht dasselbe Design aufweisen, vorausgesetzt, sowohl die DX- als auch die GL-Engine Zugriff auf dieselben stabilen Daten haben. In der Zwischenzeit wäre es sehr teuer und es müsste eine Reihe von Systemen neu geschrieben werden, um beispielsweise die Datendarstellung von a zu ändern MotionComponent.

Dies steht im Gegensatz zu dem, was wir traditionell mit OOP assoziieren, zumindest in Bezug auf die Kopplungseigenschaften und was "öffentliche Schnittstelle" im Vergleich zu "privaten Implementierungsdetails" darstellt. Natürlich sind "Implementierungsdetails" in beiden Fällen leicht zu ändern, aber in ECS ist es das Design von Daten, deren Änderung kostspielig ist (Daten sind in ECS kein Implementierungsdetail), und in OOP ist es das Design von Funktionen, deren Änderung kostspielig ist (Der Entwurf von Funktionen ist kein Implementierungsdetail in OOP.) Das ist also eine ganz andere Vorstellung von "Implementierungsdetails", und eine der Hauptattraktionen eines ECS aus der Sicht der Wartung war die in meiner Domäne. Es war einfacher, die erforderlichen Daten zu stabilisieren und ein für alle Mal richtig zu entwerfen, als all die verschiedenen Dinge, die wir mit diesen Daten tun konnten (die sich ständig ändern würden, wenn Kunden ihre Meinung änderten und neue Benutzervorschläge eintrafen). Infolgedessen sanken die Wartungskosten, als wir damit begannen, Abhängigkeiten von abstrakten Funktionen auf rohe, zentrale Daten umzulenken (wobei immer noch darauf geachtet wurde, welche Systeme auf welche Komponenten zugreifen, damit Invarianten trotz aller konzeptionellen Daten in einem vernünftigen Ausmaß beibehalten werden können global erreichbar).

Und zumindest in meinem Fall ist das ECS-SDK mit der API und allen Komponenten tatsächlich in C implementiert und weist keine Ähnlichkeit mit OOP auf. Ich habe festgestellt, dass C für einen solchen Zweck mehr als angemessen ist, da ECS-Architekturen inhärent keine OO aufweisen und eine Plug-in-Architektur gewünscht wird, die von den unterschiedlichsten Sprachen und Compilern verwendet werden kann. Die Systeme sind immer noch in C ++ implementiert, da C ++ die Dinge dort sehr bequem macht und die Systeme den Großteil der Komplexität modellieren. Dort finde ich Verwendung für viele Dinge, die näher an OOP liegen könnten, aber das ist für Implementierungsdetails. Das architektonische Design selbst ähnelt immer noch sehr prozeduralen C.

Daher finde ich es zumindest etwas verwirrend zu sagen, dass ein ECS per Definition OO ist. Zumindest machen die Grundlagen Dinge, die eine vollständige 180-Grad-Drehung von vielen der Grundprinzipien sind, die im Allgemeinen mit OOP verbunden sind, angefangen mit der Einkapselung und möglicherweise endend mit dem, was als erwünschte Kopplungseigenschaften angesehen werden würde.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.