Unreal Engine Reflectionsystem: Typen zur Laufzeit verwalten
Unreal Engine setzt auf sein eigenes Reflectionsystem, um Typinformationen zur Laufzeit abzurufen. Dies treibt Objektserialisierung, die Anzeige von Eigenschaften im Editor, die Integration von C++ und Blueprints sowie die Netzwerkkommunikation an. Das System basiert auf Codegenerierung durch den Unreal Header Tool und zwei parallelen Typenhierarchien.
Reflectionsarchitektur: UHT und generierte Dateien
Der Unreal Header Tool (UHT) durchsucht C++-Headerdateien, erkennt Makros wie UCLASS und UPROPERTY und erzeugt Code zur Typenregistrierung. Daraus entstehen zwei zentrale Dateien:
- .generated.h — enthält Makros und Vorwärtsdeklarationen.
- .gen.cpp — beinhaltet den Typenregistrierungscode, der Tausende von Zeilen umfassen kann.
Der generierte Code speichert Metadaten wie Eigenschaftsnamen, Flags und Speicheroffsets. Beispielsweise wird der Offset der CurrentValue-Eigenschaft in FAbilityAttribute über STRUCT_OFFSET registriert, sodass die Engine die Daten zur Laufzeit direkt zugreifen kann.
Zwei Typenhierarchien: UObject und FField
UE5 verwendet zwei Systeme zur Typenbeschreibung, getrennt für optimale Performance.
UObject-basierte Hierarchie
Von der Garbage Collection verwaltet, umfasst sie:
- UClass für C++-Klassen.
- UFunction für Funktionen.
- UScriptStruct für Strukturen.
- UEnum für Aufzählungen.
FField-basierte Hierarchie
Ab UE 4.25 eingeführt, um Overhead zu reduzieren – Eigenschaften hier unterliegen keiner Garbage Collection:
- FField — Basisklasse.
- FProperty — beschreibt einzelne Eigenschaften, z. B. FIntProperty oder FFloatProperty.
- Verknüpfung zwischen Hierarchien: UStruct hält einen Zeiger auf eine verkettete Liste von FField-Eigenschaften.
Wichtige FField-Features:
- Verwendet eine verkettete Liste für Kind-Elemente.
- FFieldClass mit schnellem Typencasting über Bitmasken.
- FFieldVariant kombiniert UObject- und FField-Zeiger, wobei das niederwertigste Bit den Typ unterscheidet.
Aufbau von FProperty: Daten zugreifen
FProperty bietet Werkzeuge zum Umgang mit Eigenschaften im Speicher. Kern-Elemente:
- Offset_Internal — Speicher-Offset der Eigenschaft, berechnet über STRUCT_OFFSET.
- EPropertyFlags — Flags, die das Verhalten steuern, z. B. CPF_Edit für Editor-Anpassungen.
- Zugriffs-Methoden wie ContainerPtrToValuePtr für direktes Lesen/Schreiben.
Beispiel in Aktion:
UAbilityComponent* Comp = ...;
FProperty* HealthProp = Comp->GetClass()->FindPropertyByName(TEXT("HealthAttribute"));
FAbilityAttribute* HealthPtr = HealthProp->ContainerPtrToValuePtr<FAbilityAttribute>(Comp);
float CurrentHealth = HealthPtr->CurrentValue;
Praktische Anwendungen der Reflection
Das Reflectionsystem von Unreal Engine antreibt zentrale Features:
- Serialisierung — Speichern und Laden von Objekten aus Dateien.
- Editor — Anzeige von Eigenschaften im Details-Panel mit Kategorien und individuellen Widgets.
- Blueprint-Integration — Freigabe von C++-Eigenschaften und -Funktionen für visuelles Scripting.
- Netzwerk-Replikation — Synchronisation von Daten zwischen Client und Server.
- Garbage Collection — Nachverfolgung von Objektbesitz für Speicherverwaltung.
Wichtige Erkenntnisse
- Die Reflection in Unreal Engine basiert auf Codegenerierung durch den Unreal Header Tool, nicht auf nativen C++-Features.
- Die Trennung von UObject- und FField-Hierarchien verbessert Performance und Speicherverwaltung.
- Speicher-Offsets in FProperty ermöglichen schnellen Datenzugriff zur Laufzeit.
- Das System bildet die Basis für Kernfunktionen wie Serialisierung, Editing und Networking.
- Das Beherrschen der Reflection ist essenziell für fortgeschrittene Systeme wie Ability-Komponenten oder eigene Editor-Tools.
— Editorial Team
Noch keine Kommentare.