Système de réflexion d'Unreal Engine : gestion des types à l'exécution
Unreal Engine s'appuie sur son propre système de réflexion pour accéder aux informations de types pendant l'exécution. Cela alimente la sérialisation des objets, l'affichage des propriétés dans l'éditeur, l'intégration C++ et Blueprint, ainsi que la communication réseau. Le système repose sur la génération de code via l'Unreal Header Tool et deux hiérarchies de types parallèles.
Architecture de la réflexion : UHT et fichiers générés
L'Unreal Header Tool (UHT) analyse les fichiers d'en-tête C++, repère les macros comme UCLASS et UPROPERTY, et génère du code pour enregistrer les types. Cela crée deux fichiers clés :
- .generated.h — contient les macros et les déclarations anticipées.
- .gen.cpp — inclut le code d'enregistrement des types, qui peut s'étendre sur des milliers de lignes.
Le code généré stocke des métadonnées comme les noms de propriétés, les drapeaux et les offsets mémoire. Par exemple, la propriété CurrentValue dans FAbilityAttribute a son offset enregistré via STRUCT_OFFSET, permettant au moteur d'accéder directement aux données à l'exécution.
Deux hiérarchies de types : UObject et FField
UE5 utilise deux systèmes pour décrire les types, séparés pour optimiser les performances.
Hiérarchie basée sur UObject
Gérée par le ramasse-miettes, elle inclut :
- UClass pour les classes C++.
- UFunction pour les fonctions.
- UScriptStruct pour les structs.
- UEnum pour les énumérations.
Hiérarchie basée sur FField
Introduite dans UE 4.25 pour réduire la surcharge, les propriétés ici échappent au ramasse-miettes :
- FField — classe de base.
- FProperty — décrit les propriétés individuelles, comme FIntProperty ou FFloatProperty.
- Lien entre les hiérarchies : UStruct contient un pointeur vers une liste chaînée de propriétés FField.
Fonctionnalités clés de FField :
- Utilise une liste chaînée pour les éléments enfants.
- Inclut FFieldClass avec un cast de type rapide via des masques de bits.
- FFieldVariant combine des pointeurs UObject et FField, en utilisant le bit bas pour distinguer les types.
Anatomie de FProperty : accès aux données
FProperty fournit des outils pour manipuler les propriétés en mémoire. Éléments principaux :
- Offset_Internal — offset mémoire de la propriété, calculé via STRUCT_OFFSET.
- EPropertyFlags — drapeaux dictant le comportement, comme CPF_Edit pour les ajustements dans l'éditeur.
- Méthodes d'accès comme ContainerPtrToValuePtr pour lecture/écriture directe.
Exemple en action :
UAbilityComponent* Comp = ...;
FProperty* HealthProp = Comp->GetClass()->FindPropertyByName(TEXT("HealthAttribute"));
FAbilityAttribute* HealthPtr = HealthProp->ContainerPtrToValuePtr<FAbilityAttribute>(Comp);
float CurrentHealth = HealthPtr->CurrentValue;
Utilisations pratiques de la réflexion
Le système de réflexion d'Unreal Engine pilote des fonctionnalités essentielles :
- Sérialisation — sauvegarde et chargement des objets depuis des fichiers.
- Éditeur — affichage des propriétés dans le panneau Détails avec catégories et widgets personnalisés.
- Intégration Blueprint — exposition des propriétés et fonctions C++ au scripting visuel.
- Réplication réseau — synchronisation des données entre client et serveur.
- Ramasse-miettes — suivi de la propriété des objets pour la gestion mémoire.
Points clés à retenir
- La réflexion d'Unreal Engine repose sur la génération de code par l'Unreal Header Tool, et non sur les fonctionnalités natives de C++.
- La séparation des hiérarchies UObject et FField améliore les performances et la gestion mémoire.
- Les offsets mémoire dans FProperty permettent un accès rapide aux données à l'exécution.
- Le système sous-tend les fonctions essentielles du moteur comme la sérialisation, l'édition et le réseau.
- Maîtriser la réflexion est indispensable pour développer des systèmes avancés comme les composants d'abilities ou des outils d'éditeur personnalisés.
— Editorial Team
Aucun commentaire pour le moment.