• UE4类型系统、语言修饰符和元数据


    在编译之前,通过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

    UStructUScriptStructUFunctionUClass的基类,统一提供了对属性的支持;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

     

    语言修饰符

    结构体说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Structs/Specifiers/index.html

    类说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Classes/#%E7%B1%BB%E8%AF%B4%E6%98%8E%E7%AC%A6

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Classes/Specifiers/index.html 

    接口说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Interfaces/#%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E%E7%AC%A6

    函数说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Functions/index.html

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Functions/Specifiers/index.html

    属性说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Properties/Specifiers/index.html

    元数据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说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E5%88%97%E4%B8%BE%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    结构体元数据UMetaData说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E7%BB%93%E6%9E%84%E4%BD%93%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Structs/Specifiers/#%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    类元数据UMetaData说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E7%B1%BB%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Classes/Specifiers/#%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    接口元数据UMetaData说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E6%8E%A5%E5%8F%A3%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    函数元数据UMetaData说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E5%87%BD%E6%95%B0%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    属性元数据UMetaData说明符

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/#%E5%B1%9E%E6%80%A7%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    https://docs.unrealengine.com/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Properties/Specifiers/#%E5%85%83%E6%95%B0%E6%8D%AE%E8%AF%B4%E6%98%8E%E7%AC%A6

    参考

    《InsideUE4》UObject(二)类型系统概述

    《InsideUE4》UObject(三)类型系统设定和结构

    《InsideUE4》UObject(十二)类型系统-总结

    《InsideUE4》UObject(十三)类型系统-反射实战

    UFUNCTION/UPROPERTY/UCLASS

  • 相关阅读:
    C# linq根据属性分组,并累加计算
    AR模板分组显示(C#打印)
    显示单据信息(类似打印)
    C#同步方法中调用异步方法
    win10 Git安装或者使用出现128问题
    简单的分页查询实现
    数据库批量插入【数据库】
    VideoView
    音乐播放
    画画板案例
  • 原文地址:https://www.cnblogs.com/kekec/p/14274356.html
Copyright © 2020-2023  润新知