在编译之前,通过UHT扫描头文件中特定的宏来生成相关代码(*.generated.h / *.gen.cpp),然后再一起编译链接进游戏,来生成类型系统、扩展语言修饰符和收集元数据UMetaData
类型系统在对象之外,提供了一个静态信息载体,不仅描述了对象自身,还能构建起来对象之间的派生从属关系
通过查询类型系统数据,可实现强大的运行时类型识别(RTTI,Run-Time Type Identification)。例如:根据类型创建对象,遍历和修改属性成员,根据名字来调用函数。
默认对象(Class Default Object,简称CDO)、反射(Reflection)、垃圾回收(Garbage Collection,简称GC)、序列化(Serialization)都是在类型系统的基础上实现的
通过修饰符来在编程语言层面扩展c++能力,引擎底层提供对修饰符实现,与引擎深度结合,程序员可通过配置修饰符让对象、属性或函数拥有更强大的能力
修饰符可优雅地实现c++与蓝图的互操作、编辑器支持、网络同步等方面的功能
例如:Config修饰符来从指定ini文件中读取数据、Transient修饰符来指明不需要序列化、Exec修饰符来指明该函数可被控制台调用
Replicated修饰符给属性加上同步属性、Server修饰符表明该函数为一个对服务端的RPC调用,等等
元数据UMetaData其实就是个键值对的集合,用于为编辑器提供分类、友好名字、提示等信息,Android、IOS、DS版本不包含此信息(相关逻辑包裹在宏WITH_EDITORONLY_DATA中)
类型系统
① UField为类型系统的统一基类,可以方便获取元数据UMetaData
② UStruct为UScriptStruct、UFunction、UClass的基类,统一提供了对属性的支持;UStruct* SuperStruct指向继承的基类
③ UFunction只可包含属性,来作为函数的输入输出参数
④ FProperty为属性的基类,具体包括:
FBoolProperty
FInt8Property、FInt16Property、FIntProperty、FInt64Property
FByteProperty、FUInt16Property、FUInt32Property、FUInt64Property
FFloatProperty、FDoubleProperty
FNameProperty、FTextProperty、FStrProperty
FArrayProperty、FMapProperty、FSetProperty
FMulticastInlineDelegateProperty、FMulticastSparseDelegateProperty、FDelegateProperty
FEnumProperty
FStructProperty
FObjectProperty、FInterfaceProperty、FClassProperty
FWeakObjectProperty、FLazyObjectProperty、FSoftObjectProperty、FSoftClassProperty
UEnum
① 被宏UENUM修饰的普通的枚举
② 被宏UENUM修饰的enum class的类型
/** The network role of an actor on a local/remote network context */ UENUM() enum ENetRole { /** No role at all. */ ROLE_None, /** Locally simulated proxy of this actor. */ ROLE_SimulatedProxy, /** Locally autonomous proxy of this actor. */ ROLE_AutonomousProxy, /** Authoritative control over the actor. */ ROLE_Authority, ROLE_MAX, }; // Must match enum ESamplerFilter in RHIDefinitions.h UENUM() enum class ETextureSamplerFilter : uint8 { Point, Bilinear, Trilinear, AnisotropicPoint, AnisotropicLinear, }; /** * Determines case sensitivity options for string comparisons. * @note Mirrored from EngineSourceRuntimeCorePublicContainersUnrealString.h */ UENUM() namespace ESearchCase { enum Type { CaseSensitive, IgnoreCase, }; }
UScriptStruct
被宏USTRUCT修饰的结构体的类型为UScriptStruct,只可包含属性,可以理解为C++中的POD(Plain Old Data)结构体。
是一种“轻量UObject,拥有和UObject一样的反射支持,序列化,网络复制等。但其不受GC管理。
/** * A point or direction FVector in 3d space. * @note The full C++ class is located here: EngineSourceRuntimeCorePublicMathVector.h */ USTRUCT(immutable, noexport, BlueprintType, meta=(HasNativeMake="Engine.KismetMathLibrary.MakeVector", HasNativeBreak="Engine.KismetMathLibrary.BreakVector")) struct FVector { UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Vector, SaveGame) float X; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Vector, SaveGame) float Y; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Vector, SaveGame) float Z; }; /** * A plane definition in 3D space. * @note The full C++ class is located here: EngineSourceRuntimeCorePublicMathPlane.h */ USTRUCT(immutable, noexport, BlueprintType) struct FPlane : public FVector { UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Plane, SaveGame) float W; }; /** Struct to help hold information about packages needing to be fully-loaded for DLC, etc. */ USTRUCT() struct FFullyLoadedPackagesInfo { GENERATED_USTRUCT_BODY() /** When to load these packages */ UPROPERTY() TEnumAsByte<enum EFullyLoadPackageType> FullyLoadType; /** When this map or gametype is loaded, the packages in the following array will be loaded and added to root, then removed from root when map is unloaded */ UPROPERTY() FString Tag; /** The list of packages that will be fully loaded when the above Map is loaded */ UPROPERTY() TArray<FName> PackagesToLoad; /** List of objects that were loaded, for faster cleanup */ UPROPERTY() TArray<class UObject*> LoadedObjects; FFullyLoadedPackagesInfo() : FullyLoadType(0) { } }; /** * FFocusEvent is used when notifying widgets about keyboard focus changes * It is passed to event handlers dealing with keyboard focus */ USTRUCT(BlueprintType) struct FFocusEvent { GENERATED_USTRUCT_BODY() public: /** * UStruct Constructor. Not meant for normal usage. */ FFocusEvent() : Cause(EFocusCause::SetDirectly) , UserIndex(0) { } /** * Constructor. Events are immutable once constructed. * * @param InCause The cause of the focus event */ FFocusEvent(const EFocusCause InCause, uint32 InUserIndex) : Cause(InCause) , UserIndex(InUserIndex) { } /** * Queries the reason for the focus change * * @return The cause of the focus change */ EFocusCause GetCause() const { return Cause; } /** * Queries the user that is changing focus * * @return The user that is changing focus */ uint32 GetUser() const { return UserIndex; } private: /** The cause of the focus change */ EFocusCause Cause; /** User that is changing focus*/ uint32 UserIndex; };
UClass
被宏UCLASS修饰的UObject的类型为UClass,可包含属性和函数
在UObject对象上调用GetClass()可获得它的UClass对象,在UClass对象上调用GetClass()返回的是自己本身,这样可以用来区分对象和类型数据。
UCLASS(Transient, BlueprintType) class UMG_API UUMGSequencePlayer : public UObject, public IMovieScenePlayer // IMovieScenePlayer为普通的c++纯虚类 { GENERATED_UCLASS_BODY() // ... ... }; /** * The user widget is extensible by users through the WidgetBlueprint. */ UCLASS(Abstract, editinlinenew, BlueprintType, Blueprintable, meta=( DontUseGenericSpawnObject="True", DisableNativeTick) ) class UMG_API UUserWidget : public UWidget, public INamedSlotInterface // INamedSlotInterface为虚幻Interface类型 { GENERATED_BODY() friend class SObjectWidget; public: UUserWidget(const FObjectInitializer& ObjectInitializer); //UObject interface virtual class UWorld* GetWorld() const override; virtual void PostDuplicate(bool bDuplicateForPIE) override; virtual void BeginDestroy() override; virtual void PostLoad() override; virtual void Serialize(FArchive& Ar) override; //~ End UObject Interface void DuplicateAndInitializeFromWidgetTree(UWidgetTree* InWidgetTree); virtual bool Initialize(); EWidgetTickFrequency GetDesiredTickFrequency() const { return TickFrequency; } // ... ... public: // ... ... /** * Adds it to the game's viewport and fills the entire screen, unless SetDesiredSizeInViewport is called * to explicitly set the size. * * @param ZOrder The higher the number, the more on top this widget will be. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="User Interface|Viewport", meta=( AdvancedDisplay = "ZOrder" )) void AddToViewport(int32 ZOrder = 0); /** * Adds the widget to the game's viewport in a section dedicated to the player. This is valuable in a split screen * game where you need to only show a widget over a player's portion of the viewport. * * @param ZOrder The higher the number, the more on top this widget will be. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="User Interface|Viewport", meta=( AdvancedDisplay = "ZOrder" )) bool AddToPlayerScreen(int32 ZOrder = 0); /** * Removes the widget from the viewport. */ UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="User Interface|Viewport", meta=( DeprecatedFunction, DeprecationMessage="Use RemoveFromParent instead" )) void RemoveFromViewport(); /** * Removes the widget from its parent widget. If this widget was added to the player's screen or the viewport * it will also be removed from those containers. */ virtual void RemoveFromParent() override; // ... ... public: // ... ... /** Setting this flag to true, allows this widget to accept focus when clicked, or when navigated to. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Interaction") uint8 bIsFocusable : 1; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Input") uint8 bStopAction : 1; /** If a widget has an implemented tick blueprint function */ UPROPERTY() uint8 bHasScriptImplementedTick : 1; /** If a widget has an implemented paint blueprint function */ UPROPERTY() uint8 bHasScriptImplementedPaint : 1; protected: /** Has this widget been initialized by its class yet? */ uint8 bInitialized : 1; /** If we're stopping all animations, don't allow new animations to be created as side-effects. */ uint8 bStoppingAllAnimations : 1; // ... ... }; UCLASS(abstract, BlueprintType, MinimalAPI, HideCategories = (Thumbnail)) class UMaterialInterface : public UObject, public IBlendableInterface, public IInterface_AssetUserData // UMaterialInterface为UObject,继承了2个Interface { GENERATED_UCLASS_BODY() /** SubsurfaceProfile, for Screen Space Subsurface Scattering */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Material, meta = (DisplayName = "Subsurface Profile")) class USubsurfaceProfile* SubsurfaceProfile; /* -------------------------- */ /** A fence to track when the primitive is no longer used as a parent */ FRenderCommandFence ParentRefFence; protected: /** The Lightmass settings for this object. */ UPROPERTY(EditAnywhere, Category=Lightmass) struct FLightmassMaterialInterfaceSettings LightmassSettings; // ... ... public: //~ Begin IInterface_AssetUserData Interface ENGINE_API virtual void AddAssetUserData(UAssetUserData* InUserData) override; ENGINE_API virtual void RemoveUserDataOfClass(TSubclassOf<UAssetUserData> InUserDataClass) override; ENGINE_API virtual UAssetUserData* GetAssetUserDataOfClass(TSubclassOf<UAssetUserData> InUserDataClass) override; //~ End IInterface_AssetUserData Interface // ... ... //~ Begin Begin Interface IBlendableInterface ENGINE_API virtual void OverrideBlendableSettings(class FSceneView& View, float Weight) const override; //~ Begin End Interface IBlendableInterface /** Walks up parent chain and finds the base Material that this is an instance of. Just calls the virtual GetMaterial() */ UFUNCTION(BlueprintCallable, Category="Rendering|Material") ENGINE_API UMaterial* GetBaseMaterial(); // ... ... };
UInterface
一个自定义的UObject类,只能有一个UObject基类,但可以有多个UInterface接口
UINTERFACE宏即UCLASS宏。 #define UINTERFACE(...) UCLASS()
因此,接口也是被宏UCLASS修饰的UObject,其类型也为UClass,但它只可包含函数
在UClass里保存了一个TArray<FImplementedInterface> Interfaces数组,FImplementedInterface中的成员UClass* Class来支持查询当前类实现了那些接口。
UINTERFACE需要定义两个类:一个是UXXXInterface类,继承UInterface,其中什么数据都没有。另一个是IXXXInterface类,什么都不继承。
UINTERFACE用两个类来实现,可以避免菱形继承导致的虚表扩张及二义性。外部类如果要继承接口的话,只用继承IXXXInterface类即可,非常干净。
UINTERFACE(meta=( CannotImplementInterfaceInBlueprint )) class UMG_API UNamedSlotInterface : public UInterface { GENERATED_UINTERFACE_BODY() // 使用该宏,需要在cpp中实现UNamedSlotInterface::UNamedSlotInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) {}构造函数 }; class UMG_API INamedSlotInterface { GENERATED_IINTERFACE_BODY() public: /** */ virtual void GetSlotNames(TArray<FName>& SlotNames) const = 0; /** */ virtual UWidget* GetContentForSlot(FName SlotName) const = 0; /** */ virtual void SetContentForSlot(FName SlotName, UWidget* Content) = 0; /** */ bool ContainsContent(UWidget* Content) const; /** */ void ReleaseNamedSlotSlateResources(bool bReleaseChildren); #if WITH_EDITOR void SetNamedSlotDesignerFlags(EWidgetDesignFlags NewFlags); #endif }; // --------------------------------------------------------------------------------------------------------------------------------- UINTERFACE() class MOVIESCENE_API UMovieSceneCustomClockSource : public UInterface { GENERATED_BODY() }; /** * */ class IMovieSceneCustomClockSource { public: GENERATED_BODY() UFUNCTION() virtual void OnTick(float DeltaSeconds, float InPlayRate) {} UFUNCTION() virtual void OnStartPlaying(const FQualifiedFrameTime& InStartTime) {} UFUNCTION() virtual void OnStopPlaying(const FQualifiedFrameTime& InStopTime) {} UFUNCTION() virtual FFrameTime OnRequestCurrentTime(const FQualifiedFrameTime& InCurrentTime, float InPlayRate) { return 0; } }; // --------------------------------------------------------------------------------------------------------------------------------- /** Interface for assets which contain gameplay tags */ UINTERFACE(Blueprintable, MinimalAPI, meta=(CannotImplementInterfaceInBlueprint)) class UGameplayTagAssetInterface : public UInterface { GENERATED_UINTERFACE_BODY() // 使用该宏,需要在cpp中实现UGameplayTagAssetInterface::UGameplayTagAssetInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) {}构造函数 }; class GAMEPLAYTAGS_API IGameplayTagAssetInterface { GENERATED_IINTERFACE_BODY() /** * Get any owned gameplay tags on the asset * * @param OutTags [OUT] Set of tags on the asset */ UFUNCTION(BlueprintCallable, Category = GameplayTags) virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const=0; /** * Check if the asset has a gameplay tag that matches against the specified tag (expands to include parents of asset tags) * * @param TagToCheck Tag to check for a match * * @return True if the asset has a gameplay tag that matches, false if not */ UFUNCTION(BlueprintCallable, Category=GameplayTags) virtual bool HasMatchingGameplayTag(FGameplayTag TagToCheck) const; /** * Check if the asset has gameplay tags that matches against all of the specified tags (expands to include parents of asset tags) * * @param TagContainer Tag container to check for a match * * @return True if the asset has matches all of the gameplay tags, will be true if container is empty */ UFUNCTION(BlueprintCallable, Category=GameplayTags) virtual bool HasAllMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const; /** * Check if the asset has gameplay tags that matches against any of the specified tags (expands to include parents of asset tags) * * @param TagContainer Tag container to check for a match * * @return True if the asset has matches any of the gameplay tags, will be false if container is empty */ UFUNCTION(BlueprintCallable, Category=GameplayTags) virtual bool HasAnyMatchingGameplayTags(const FGameplayTagContainer& TagContainer) const; };
FProperty
FXXXProperty用来描述:
① USTRUCT宏修饰的结构体中被UPROPERTY宏修饰的成员变量
② UCLASS宏修饰的UObject中被UPROPERTY宏修饰的成员变量
③ UFUNCTION宏修饰的成员函数的参数及返回值
4.25版本之后,属性相关类型的名称从UXXXProperty修改为FXXXProperty。继承的基类也不再是UField --> UObject,而是FField。
如果你在代码中仍然使用UXXXProperty,编译器会将其宏替换为FXXXProperty,并得到如下编译warning:
warning C4996: UProperty has been renamed to FProperty Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.
详见:G:svnUnrealEngineEngineSourceRuntimeCoreUObjectPublicUObjectDefineUPropertyMacros.h
另外,可以调用FField* FField::CreateFromUField(UField* InField)函数将一个UField转换为FField
布尔、整型、浮点型
FBoolProperty(bool、TEnumAsByte<ENetRole>)
FNumericProperty:FInt8Property(int8)、FInt16Property(int16)、FIntProperty(int32)、FInt64Property(int64)、
FByteProperty(uint8)、FUInt16Property(uint16)、FUInt32Property(uint32)、FUInt64Property(uint64)、
FFloatProperty(float)、FDoubleProperty(double)
字符串
FName:FNameProperty
FText:FTextProperty
FString:FStrProperty
容器
TArray:FArrayProperty
TMap:FMapProperty
TSet:FSetProperty
Delegate
DECLARE_DYNAMIC_MULTICAST_DELEGATE_*:FMulticastInlineDelegateProperty
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE*:FMulticastSparseDelegateProperty
DECLARE_DYNAMIC_DELEGATE*:FDelegateProperty
枚举、结构体、接口、Object等复合类型
UENUM宏修饰的enum class:FEnumProperty
USTRUCT宏修饰的结构体(如:FVector、FPlane、FSoftObjectPath、FSoftClassPath):FStructProperty
TScriptInterface<UNamedSlotInterface>、TScriptInterface <INamedSlotInterface>:FInterfaceProperty
UObject*、UStruct、UScriptStruct、UFunction、UEnum、UField:FObjectProperty
UClass*、TSubclassOf<UObject>:FClassProperty
TWeakObjectPtr<UObject>:FWeakObjectProperty 注:FWeakObjectPtr不能作为属性
TLazyObjectPtr<UObject>:FLazyObjectProperty 注:FLazyObjectPtr不能作为属性
TSoftObjectPtr<UObject>:FSoftObjectProperty 注1:FSoftObjectPath的类型为FStructProperty 注2:FSoftObjectPtr不能作为属性
TSoftClassPtr<UObject>:FSoftClassProperty 注:FSoftClassPath的类型为FStructProperty
语言修饰符
结构体说明符
类说明符
接口说明符
函数说明符
属性说明符
元数据UMetaData
UMetaData虽然在UPackage中,但是UField对其做了封装,并提供了GetMetaData的接口。
UMetaData通过TMap< FWeakObjectPtr, TMap<FName, FString> > ObjectMetaDataMap来存放Object的键值对信息
UENUM元数据
UENUM(meta=(ScriptName="EnvDirectionType")) namespace EEnvDirection { enum Type { TwoPoints UMETA(DisplayName="Two Points",ToolTip="Direction from location of one context to another."), Rotation UMETA(ToolTip="Context's rotation will be used as a direction."), }; }
USTRUCT元数据
USTRUCT(meta=(DisplayName="Static Mesh Control", Category="Controls", ShowVariableNameInTitle)) struct CONTROLRIG_API FRigUnit_Control_StaticMesh : public FRigUnit_Control { GENERATED_BODY() FRigUnit_Control_StaticMesh(); RIGVM_METHOD() virtual void Execute(const FRigUnitContext& Context) override; /** The the transform the mesh will be rendered with (applied on top of the control's transform in the viewport) */ UPROPERTY(meta=(Input)) FTransform MeshTransform; };
UCLASS元数据
UCLASS(BlueprintType, meta=(DisplayName="Empty Comp Shot", ShortTooltip="A simple base actor used to composite multiple render layers together.")) class COMPOSURE_API ACompositingElement : public AComposurePipelineBaseActor, public ICompImageColorPickerInterface { GENERATED_UCLASS_BODY() // ... ... protected: /*********************************/ // Pipeline Passes // - protected to prevent users from directly modifying these lists (use the accessor functions instead) UPROPERTY(EditAnywhere, Instanced, BlueprintReadOnly, BlueprintGetter = GetInputsList, Category = "Composure|Input", meta=(ShowOnlyInnerProperties)) TArray<UCompositingElementInput*> Inputs; UPROPERTY(EditAnywhere, Instanced, BlueprintReadOnly, BlueprintGetter = GetTransformsList, Category = "Composure|Transform/Compositing Passes", meta=(DisplayName = "Transform Passes", ShowOnlyInnerProperties, DisplayAfter="Inputs")) TArray<UCompositingElementTransform*> TransformPasses; UPROPERTY(EditAnywhere, Instanced, BlueprintReadOnly, BlueprintGetter = GetOutputsList, Category = "Composure|Output", meta = (ShowOnlyInnerProperties)) TArray<UCompositingElementOutput*> Outputs; // ... ... public: // ... ... /*********************************/ // Pass Management UFUNCTION(BlueprintCallable, Category = "Composure", meta = (DeterminesOutputType = "InputType")) UCompositingElementInput* FindInputPass(UPARAM(meta = (AllowAbstract = "false"))TSubclassOf<UCompositingElementInput> InputType, UTexture*& PassResult, FName OptionalPassName = NAME_None); UFUNCTION(BlueprintCallable, Category = "Composure", meta = (DeterminesOutputType = "TransformType")) UCompositingElementTransform* FindTransformPass(UPARAM(meta = (AllowAbstract = "false"))TSubclassOf<UCompositingElementTransform> TransformType, UTexture*& PassResult, FName OptionalPassName = NAME_None); UFUNCTION(BlueprintCallable, Category = "Composure", meta = (DeterminesOutputType = "OutputType")) UCompositingElementOutput* FindOutputPass(UPARAM(meta = (AllowAbstract = "false"))TSubclassOf<UCompositingElementOutput> OutputType, FName OptionalPassName = NAME_None); // ... ... };
UINTERFACE元数据
UINTERFACE(MinimalAPI, meta=(CannotImplementInterfaceInBlueprint)) class UNavRelevantInterface : public UInterface { GENERATED_UINTERFACE_BODY() // 使用该宏,需要在cpp中实现UNamedSlotInterface::UNamedSlotInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) {}构造函数 }; class INavRelevantInterface { GENERATED_IINTERFACE_BODY() /** Prepare navigation modifiers */ virtual void GetNavigationData(FNavigationRelevantData& Data) const {} /** Get bounds for navigation octree */ virtual FBox GetNavigationBounds() const { return FBox(ForceInit); } // ... ... };
可通过命令Metadata.Dump来Dump所有的元信息到日志中
[2021.04.23-06.51.36:018][744]LogMetaData: METADATA /Script/CoreUObject.PackageMetaData [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.JoinabilitySettings: Comment=// Circular dependency on Core vs UHT means we have to noexport these structs so tools can build [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.JoinabilitySettings: ModuleRelativePath=Public/UObject/CoreOnline.h [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.UniqueNetIdWrapper: ModuleRelativePath=Public/UObject/CoreOnline.h [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Guid: BlueprintType=true [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Guid: Comment=/** A globally unique identifier (mirrored from Guid.h) */ [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Guid: ModuleRelativePath=Public/UObject/NoExportTypes.h [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector: BlueprintType=true [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector: Comment=/** * A point or direction FVector in 3d space. * @note The full C++ class is located here: EngineSourceRuntimeCorePublicMathVector.h */ [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector: HasNativeBreak=Engine.KismetMathLibrary.BreakVector [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector: HasNativeMake=Engine.KismetMathLibrary.MakeVector [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector: ModuleRelativePath=Public/UObject/NoExportTypes.h [2021.04.23-06.51.36:018][744]LogMetaData: /Script/CoreUObject.Vector4: BlueprintType=true 。。。 。。。 [2021.04.23-06.51.37:464][744]LogMetaData: /Script/AITestSuite.TestPawnAction_CallFunction: IncludePath=Actions/TestPawnAction_CallFunction.h [2021.04.23-06.51.37:464][744]LogMetaData: /Script/AITestSuite.TestPawnAction_CallFunction: ModuleRelativePath=Classes/Actions/TestPawnAction_CallFunction.h [2021.04.23-06.51.37:464][744]LogMetaData: METADATA /Engine/EditorResources/SequenceRecorder/Countdown.PackageMetaData [2021.04.23-06.51.37:464][744]LogMetaData: Root: PackageLocalizationNamespace=E807D18340E352E3392B57A9706DA988 [2021.04.23-06.51.37:464][744]LogMetaData: METADATA /Script/SequenceRecorderSections.PackageMetaData [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneParticleTrackSectionRecorder:OnTriggered: ModuleRelativePath=Public/MovieSceneParticleTrackSectionRecorder.h [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneParticleTrackSectionRecorder: IncludePath=MovieSceneParticleTrackSectionRecorder.h [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneParticleTrackSectionRecorder: IsBlueprintBase=false [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneParticleTrackSectionRecorder: ModuleRelativePath=Public/MovieSceneParticleTrackSectionRecorder.h [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneVisibilitySectionRecorderSettings: IncludePath=MovieSceneVisibilitySectionRecorderSettings.h [2021.04.23-06.51.37:464][744]LogMetaData: /Script/SequenceRecorderSections.MovieSceneVisibilitySectionRecorderSettings: ModuleRelativePath=Public/MovieSceneVisibilitySectionRecorderSettings.h
obj classes // 按继承关系打印出类型信息及被淘汰的UProperty
[2021.04.26-20.49.25:237][860]Object (40) [2021.04.26-20.49.25:237][860] 。。。 。。。 [2021.04.26-20.49.25:676][860] Field (48) [2021.04.26-20.49.25:676][860] Struct (176) [2021.04.26-20.49.25:676][860] ScriptStruct (192) [2021.04.26-20.49.25:676][860] UserDefinedStruct (264) [2021.04.26-20.49.25:676][860] AISenseBlueprintListener (264) [2021.04.26-20.49.25:676][860] Class (624) [2021.04.26-20.49.25:677][860] DynamicClass (752) [2021.04.26-20.49.25:677][860] LinkerPlaceholderClass (1064) [2021.04.26-20.49.25:677][860] BlueprintGeneratedClass (880) [2021.04.26-20.49.25:677][860] WidgetBlueprintGeneratedClass (944) [2021.04.26-20.49.25:677][860] AnimBlueprintGeneratedClass (1528) [2021.04.26-20.49.25:677][860] Function (224) [2021.04.26-20.49.25:677][860] DelegateFunction (224) [2021.04.26-20.49.25:678][860] SparseDelegateFunction (240) [2021.04.26-20.49.25:678][860] LinkerPlaceholderFunction (664) [2021.04.26-20.49.25:678][860] Enum (96) [2021.04.26-20.49.25:678][860] UserDefinedEnum (176) [2021.04.26-20.49.25:678][860] Property (112) [2021.04.26-20.49.25:678][860] EnumProperty (128) [2021.04.26-20.49.25:678][860] ArrayProperty (120) [2021.04.26-20.49.25:679][860] ObjectPropertyBase (120) [2021.04.26-20.49.25:679][860] ObjectProperty (120) [2021.04.26-20.49.25:679][860] ClassProperty (128) [2021.04.26-20.49.25:679][860] LazyObjectProperty (120) [2021.04.26-20.49.25:679][860] SoftObjectProperty (120) [2021.04.26-20.49.25:679][860] SoftClassProperty (128) [2021.04.26-20.49.25:679][860] WeakObjectProperty (120) [2021.04.26-20.49.25:680][860] BoolProperty (120) [2021.04.26-20.49.25:680][860] NumericProperty (112) [2021.04.26-20.49.25:680][860] ByteProperty (120) [2021.04.26-20.49.25:680][860] DoubleProperty (112) [2021.04.26-20.49.25:680][860] FloatProperty (112) [2021.04.26-20.49.25:680][860] IntProperty (112) [2021.04.26-20.49.25:680][860] Int8Property (112) [2021.04.26-20.49.25:681][860] Int16Property (112) [2021.04.26-20.49.25:681][860] Int64Property (112) [2021.04.26-20.49.25:681][860] UInt16Property (112) [2021.04.26-20.49.25:681][860] UInt32Property (112) [2021.04.26-20.49.25:681][860] UInt64Property (112) [2021.04.26-20.49.25:681][860] DelegateProperty (120) [2021.04.26-20.49.25:681][860] InterfaceProperty (120) [2021.04.26-20.49.25:682][860] MapProperty (152) [2021.04.26-20.49.25:682][860] MulticastDelegateProperty (120) [2021.04.26-20.49.25:682][860] MulticastInlineDelegateProperty (120) [2021.04.26-20.49.25:682][860] MulticastSparseDelegateProperty (120) [2021.04.26-20.49.25:682][860] NameProperty (112) [2021.04.26-20.49.25:682][860] SetProperty (144) [2021.04.26-20.49.25:682][860] StrProperty (112) [2021.04.26-20.49.25:683][860] StructProperty (120) [2021.04.26-20.49.25:683][860] TextProperty (112) 。。。 。。。
枚举元数据UMetaData说明符
结构体元数据UMetaData说明符
类元数据UMetaData说明符
接口元数据UMetaData说明符
函数元数据UMetaData说明符
属性元数据UMetaData说明符
参考
《InsideUE4》UObject(三)类型系统设定和结构