In meiner ECS-Implementierung verwende ich bitweise Operationen (wie in diesem Thread beschrieben und dargestellt ), um einer Entität mitzuteilen, aus welcher Art von Komponenten sie derzeit besteht. Meine Entity
Klasse hat also folgendes Mitglied:
unsigned long m_CompMask;
Die verschiedenen Komponententypen werden dann als definiert enum
, deren Elementwerte alle Zweierpotenzen sind:
enum ComponentType
{
COMP_TYPE_UNKNOWN = 0,
COMP_TYPE_PERSON = 1,
COMP_TYPE_RENDERABLE = 2,
COMP_TYPE_MOVEABLE = 4,
[...]
};
Jedes Mal, wenn eine neue Komponente zu meiner Entitätsinstanz hinzugefügt wird, führe ich die folgende Bitoperation aus, um die Maske zu aktualisieren (wobei newType Mitglied der enum
oben genannten ist):
m_CompMask |= newType;
Mit diesem Ansatz kann ich effizient prüfen, ob eine bestimmte Entitätsinstanz eine bestimmte Komponente enthält (und daher für ein bestimmtes System relevant sein kann), z.
return (m_CompMask & type);
Der begrenzende Faktor bei diesem Ansatz ist jedoch die m_CompMask
Variable, da sie nicht mehr als 64 Komponententypen verarbeiten kann (wenn ich sie auf erhöhe unsigned long long
).
Ich erwarte nicht, dass ich in meinem aktuellen Projekt mehr als das brauche, aber ich würde trotzdem gerne einige Ideen zu Alternativen hören, die mehr als 64 Typen zulassen (wie es große Spiele sicherlich müssen) und gleichzeitig die Leichtigkeit und Effizienz von beibehalten diese bitweisen Operationen so viel wie möglich? Irgendwelche Ideen, wie dies in "richtigen großen" Projekten gehandhabt wird ?
quelle
Antworten:
Um die anderen Antworten hier zu ergänzen, können Sie so etwas wie den folgenden Code verwenden, um einen Bit-Satz beliebiger Länge zu erhalten, der bei Bedarf wächst. Mit dieser Methode können Sie sogar eine einfache Form der Komprimierung durchführen. Wenn Ihre am häufigsten verwendeten Komponenten die niedrigsten ID-Werte aufweisen, verwendet die Mehrheit Ihrer Entitäten eine kleine Menge Bitset-Speicher, um ihre Komponenten zu verfolgen. Diejenigen, die seltenere Komponenten verwenden, funktionieren jedoch weiterhin ordnungsgemäß.
Wahrscheinlich vollständig robust, möchten Sie einige der Framework-Schnittstellen wie IEquatable und IComparable implementieren und einige Operatoren, GetHashCode usw. überschreiben.
quelle
Vielleicht könnten Sie ein Bitfeld im C-Stil verwenden und nach Bedarf neue Felder hinzufügen.
Da Sie nur boolesche Flags benötigen, ist eine Bitfeldstruktur viel kleiner als einfache Bools und bietet dieselben Ergebnisse und Benutzerfreundlichkeit:
quelle
Ein einfaches Beispiel für eine Datenstruktur, die diesen Zweck erfüllt:
Jetzt können Ihre Aufzählungen entweder in ein Wörterbuch oder in ein Array indizieren. Ich nehme an, es ist etwas schwieriger zu handhaben, aber ich habe nicht viel über dieses Ende der Dinge nachgedacht.
Vielleicht wird nur ein Array davon
LongerBitMask
automatisch generiert? Dann mit der Aufzählung hinein indizieren? Stellen Sie einfach sicher, dass Sie nur am Ende der Aufzählungen hinzufügen. Andernfalls haben Sie Komponenten, die Werte ändern.Einige statische Codes:
Stellen Sie Ihre Komponenten auf ihre Standard-Enum-Werte 0 bis 127 ein (machen Sie sie nicht zu zweit). Dann können Sie Ihre Bitmasken abrufen mit:
Jetzt definieren Ihre Systeme ihre eigenen
LongBitMask
Werte und vergleichen sie mit EntitätenMatch
.Als würde ein System seine eigene Bitmaske erstellen mit:
Wahrscheinlich stimmt etwas nicht mit meiner Bitverschiebung oder anderen Berechnungen ...
quelle
Es ist in der Tat leicht möglich, mehr als 64 Komponenten zu verwenden, selbst in einem Spiel mit mittlerem Umfang.
Erstellen Sie eine eigene Bitset-Klasse, die eine Maske beliebiger Länge enthalten kann.
quelle
Ich weiß nicht, wie dies in AAA-Spielen implementiert ist, aber Ihr Problem scheint mir recht einfach zu sein. Sie müssen nur miteinander verschmelzen:
Hier ist mein Beispielcode in C ++ 11. Ich hoffe, Sie können es in alles übersetzen, was Sie verwenden, aber wenn Sie nicht können, können Sie mich gerne fragen. Ich glaube, ich habe etwas Ähnliches im Boost gesehen, kann mich aber momentan nicht erinnern.
http://coliru.stacked-crooked.com/a/63904a428e95df94 Ausgabe:
Verwendete der Einfachheit halber die Struktur der Klasse, aber ich empfehle, sie richtig zu kapseln.
quelle