Gestern habe ich eine Präsentation von GDC Canada über das Attribut- / Verhaltensentitätssystem gelesen und finde es ziemlich gut. Ich bin mir jedoch nicht sicher, wie ich es praktisch anwenden soll, nicht nur theoretisch. Zunächst erkläre ich Ihnen kurz, wie dieses System funktioniert.
Jede Spieleinheit (Spielobjekt) besteht aus Attributen (= Daten, auf die durch Verhalten, aber auch durch 'externen Code' zugegriffen werden kann) und Verhalten (= Logik, die OnUpdate()
und enthalten OnMessage()
). So würde beispielsweise in einem Breakout-Klon jeder Baustein aus folgenden Bestandteilen bestehen (Beispiel!): PositionAttribute , ColorAttribute , HealthAttribute , RenderableBehaviour , HitBehaviour . Das letzte könnte so aussehen (es ist nur ein nicht funktionierendes Beispiel in C #):
void OnMessage(Message m)
{
if (m is CollisionMessage) // CollisionMessage is inherited from Message
{
Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith
if (otherEntity.Type = EntityType.Ball) // Collided with ball
{
int brickHealth = GetAttribute<int>(Attribute.Health); // owner's attribute
brickHealth -= otherEntity.GetAttribute<int>(Attribute.DamageImpact);
SetAttribute<int>(Attribute.Health, brickHealth); // owner's attribute
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
else if (m is AttributeChangedMessage) // Some attribute has been changed 'externally'
{
if (m.Attribute == Attribute.Health)
{
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
}
Wenn Sie an diesem System interessiert sind, können Sie hier mehr lesen (.ppt).
Meine Frage bezieht sich auf dieses System, aber im Allgemeinen auf jedes komponentenbasierte Entitätssystem. Ich habe noch nie gesehen, wie eines davon in echten Computerspielen wirklich funktioniert, weil ich keine guten Beispiele finde und wenn ich eines finde, ist es nicht dokumentiert, es gibt keine Kommentare und deshalb verstehe ich es nicht.
Also, was möchte ich fragen? So gestalten Sie die Verhaltensweisen (Komponenten). Ich habe hier auf GameDev SE gelesen, dass der häufigste Fehler darin besteht, viele Komponenten zu erstellen und einfach "alles zu einer Komponente zu machen". Ich habe gelesen, dass empfohlen wird, das Rendern nicht in einer Komponente, sondern außerhalb der Komponente durchzuführen (daher sollte es anstelle von RenderableBehaviour möglicherweise RenderableAttribute sein , und wenn für eine Entität RenderableAttribute auf true festgelegt ist Renderer
(Klasse, die nicht mit " true" zusammenhängt) Komponenten, sondern auf den Motor selbst) sollte es auf dem Bildschirm zeichnen?).
Aber wie steht es mit den Verhaltensweisen / Komponenten? Lassen Sie uns sagen , dass ich ein Niveau haben, und in der Ebene, gibt es eine Entity button
, Entity doors
und Entity player
. Wenn der Spieler mit dem Knopf kollidiert (es ist ein Bodenknopf, der durch Druck umgeschaltet wird), wird er gedrückt. Wenn der Knopf gedrückt wird, werden die Türen geöffnet. Nun, wie geht das?
Ich habe mir so etwas ausgedacht: Der Spieler hat CollisionBehaviour , das prüft, ob der Spieler mit etwas kollidiert. Wenn er mit einer Schaltfläche kollidiert, sendet er ein CollisionMessage
an die button
Entität. Die Nachricht enthält alle notwendigen Informationen: wer mit dem Button kollidiert ist. Der Button hat ToggleableBehaviour , das empfangen wird CollisionMessage
. Es wird geprüft, mit wem es kollidiert hat, und wenn das Gewicht dieser Entität groß genug ist, um die Schaltfläche umzuschalten, wird die Schaltfläche umgeschaltet. Jetzt wird das ToggledAttribute der Schaltfläche auf true gesetzt. Okay, aber was jetzt?
Sollte die Schaltfläche eine weitere Nachricht an alle anderen Objekte senden, um ihnen mitzuteilen, dass sie umgeschaltet wurden? Ich denke, wenn ich alles so machen würde, hätte ich Tausende von Nachrichten und es würde ziemlich chaotisch werden. Vielleicht ist dies besser: Die Türen prüfen ständig, ob der mit ihnen verknüpfte Knopf gedrückt ist oder nicht, und ändern das OpenedAttribute entsprechend. Aber dann bedeutet es, dass die OnUpdate()
Methode der Türen ständig etwas bewirkt (ist das wirklich ein Problem?).
Und das zweite Problem: Was ist, wenn ich mehr Arten von Knöpfen habe? Einer wird durch Druck gedrückt, der zweite durch Schießen, der dritte durch Gießen mit Wasser usw. Dies bedeutet, dass ich mich anders verhalten muss, in etwa so:
Behaviour -> ToggleableBehaviour -> ToggleOnPressureBehaviour
-> ToggleOnShotBehaviour
-> ToggleOnWaterBehaviour
Funktionieren echte Spiele so oder bin ich einfach nur dumm? Vielleicht könnte ich nur ein ToggleableBehaviour haben und es wird sich entsprechend dem ButtonTypeAttribute verhalten . Also, wenn es ein ist ButtonType.Pressure
, tut es das, wenn es ein ist ButtonType.Shot
, tut es etwas anderes ...
Also, was will ich? Ich möchte Sie fragen, ob ich es richtig mache oder ob ich einfach nur dumm bin und den Punkt der Komponenten nicht verstanden habe. Ich habe kein gutes Beispiel dafür gefunden, wie die Komponenten in Spielen wirklich funktionieren. Ich habe nur einige Tutorials gefunden, die beschreiben, wie man das Komponentensystem herstellt, aber nicht, wie man es benutzt.