• 虚幻4属性系统(反射)


    虚幻反射系统,也叫属性系统 UNREAL PROPERTY SYSTEM (REFLECTION)                               
    (由于 C++ 不支持反射,所以虚幻自己实现了一个反射系统。)
    UE中 依赖反射的系统 有垃圾回收, Editor 系统(蓝图系统),运行时查询类的信息系统。
    eg:存储 一个非反射的 UObject 裸指针 是危险,不能被垃圾回收系统进行垃圾回收。
    利用反射数据来做很多不同的事情 (枚举属性,以数据驱动的方式来获取、设置值,调用反射函数,甚至是创建新的对象)

    大多数游戏代码在运行时 享受着依赖着 UNREAL PROPERTY SYSTEM 的那些系统们带来的好处,而不需要用到 UNREAL PROPERTY SYSTEM 的东西。
    but you might find it useful when writing tool code or building gameplay systems.

    如何生成反射信息: 

    1. 在头文件 #include "FileName.generated.h"
    2. 在需要的类或者属性函数声明前 加上 宏 UENUM(), UCLASS(), USTRUCT(), UFUNCTION(), UPROPERTY() marcos 进行标识。

    因此 反射信息是可选的,如果包含 #include "FileName.generated.h",在编译工程的时候, 就会通过 Unreal Header Tool(UHT), 解析关注那些 Marcos 和 Specifiers 生成反射信息,忽略其他。 

    1.

    每种宏 括弧里可以 加入其相关特定的 specifier 和 元数据 specifier:
    Property Specifiers, Function Specifiers, Struct Specifiers, Class Specifiers, Metadata Specifiers(元数据 不只是在某个类中的):
    eg:
    UPROPERTY(EditAnywhere, Category=Pawn)
    int32 ResourcesToGather;

    UFUNCTION(BlueprintCallable, Category=Attachment)
    void SetWeaponAttachment(class UStrategyAttachment* Weapon);

    2.

    UCLASS(), USTRUCT() 需要配合 GENERATED_UCLASS_BODY() / GENERATED_USTRUCT_BODY() 宏,他们会添加 functions 和 typedefs 到类和结构体的内部。("FileName.generated.h" 定义了这些宏)
    The generated functions include things like StaticClass() / StaticStruct(),
    which make it easy to get reflection data for the type, as well as thunks used to call C++ functions from Blueprints or network replication.


    3.

    在UHT进行解析时候,如果:
    #if/#ifdef XXX(except for WITH_EDITOR and WITH_EDITORONLY_DATA)
       UPROPERTY(EditAnywhere, Category=Pawn)
       int32 ResourcesToGather;
    #endif;
    XXX为假的时候,会造成编译错误,避免之。

    4.

    UNREAL PROPERTY SYSTEM 的类型继承体系:

    UField(Base class of reflection data objects.)
       UStruct(Base class for all UObject types that contain fields. 就是 aggregate structures(anything that contains other members) 的基类)
          UClass (C++ class : contain functions or properties: UTypeName::StaticClass() )
          UScriptStruct (C++ struct 重要重要!! : limited to just properties: FTypeName::StaticStruct() )
          UFunction (C++ function : limited to just properties)
       UEnum (C++ enumeration)
       UProperty (C++ member variable or function parameter)
          (Many subclasses for different types)

    获取类类型 : UTypeName::StaticClass() 或者 Instance->GetClass()
    获取结构体类型 : FTypeName::StaticStruct() 

    5.

    To iterate over all members of a UStruct, use a TFieldIterator:

     1     template <class T>
     2     class TFieldIterator
     3     {
     4     private:
     5         /** The object being searched for the specified field */
     6         const UStruct* Struct;
     7         /** The current location in the list of fields being iterated */
     8         UField* Field;
     9         /** The index of the current interface being iterated */
    10         int32 InterfaceIndex;
    11         /** Whether to include the super class or not */
    12         const bool bIncludeSuper;
    13         /** Whether to include deprecated fields or not */
    14         const bool bIncludeDeprecated;
    15         /** Whether to include interface fields or not */
    16         const bool bIncludeInterface;
    17     public:
    18         TFieldIterator(const UStruct*                               InStruct,
    19                     EFieldIteratorFlags::SuperClassFlags         InSuperClassFlags      = EFieldIteratorFlags::IncludeSuper,  
    20                     // you only want fields introduced by InSuperClassFlags 默认是包含上一级 父类的。 
    21                     // 只对 UClass 和 UScriptStruct 有影响, 对 UFunction 没有影响
    22                     EFieldIteratorFlags::DeprecatedPropertyFlags InDeprecatedFieldFlags = EFieldIteratorFlags::IncludeDeprecated,
    23                     EFieldIteratorFlags::InterfaceClassFlags     InInterfaceFieldFlags  = EFieldIteratorFlags::ExcludeInterfaces)
    24         : Struct            ( InStruct )
    25         , Field             ( InStruct ? InStruct->Children : NULL )
    26         , InterfaceIndex    ( -1 )
    27         , bIncludeSuper     ( InSuperClassFlags      == EFieldIteratorFlags::IncludeSuper )
    28         , bIncludeDeprecated( InDeprecatedFieldFlags == EFieldIteratorFlags::IncludeDeprecated )
    29         , bIncludeInterface ( InInterfaceFieldFlags  == EFieldIteratorFlags::IncludeInterfaces && InStruct && InStruct->IsA(UClass::StaticClass()) )
    30         {
    31             IterateToNext();
    32         }
    33     }


    6.

    把类型 结构体 属性 作为一种实例。也作为一种类。

    7.

    Each type has a unique set of flags(
    eg:
    enum EStructFlags
    enum EClassFlags
    ),
    and a generic metadata storage system inherited from UField

    The keyword specifiers are usually either stored as flags or metadata, 取决于 是否是 whether they are needed in a runtime game, or only for editor functionality.
    标识符 的作用:
    1 游戏运行时需要(存为flag)
    2 仅作为编辑器的功能(存为元数据)。
    所以在运行时,可以去掉 editor-only metadata,而保持 runtime flags 一直有效

    8.

    Unreal Build Tool (UBT) and Unreal Header Tool (UHT) act in concert to generate the data that is needed to power runtime reflection.
    UBT has to scan headers to do its job, and it remembers any modules that contain a header with at least one reflected type.
    If any of those headers have changed since the last compile, UHT is invoked to harvest and update the reflection data.
    UHT parses the headers, builds up a set of reflection data, and then generates C++ code containing the reflection data (contributing to a per-module .generated.inl)
    as well as various helpers and thunk functions (per-header .generated.h).

    One of the major benefits of storing the reflection data as generated C++ code is that it is guaranteed to be in sync with the binary.
    You can never load stale or out of date reflection data since it’s compiled in with the rest of the engine code,
    and it computes member offsets/etc… at startup using C++ expressions, rather than trying to reverse engineer the packing behavior of a particular platform/compiler/optimization combo.
    它会在程序启动的时候使用C++表达式来计算成员偏移等,而不是通过针对特定平台/编译器/优化的组合中进行逆向工程。
    UHT is also built as a standalone program that doesn’t consume any generated headers, so it avoids the chicken-and-egg issues that were a common complaint with the script compiler in UE3.

    参考:

    虚幻4属性系统(反射)翻译

    UNREAL PROPERTY SYSTEM (REFLECTION)

  • 相关阅读:
    [机器学习案例1]基于KNN手写数字识别
    Android横竖屏切换View设置不同尺寸或等比例缩放的XML解决方案
    Qt之网络编程
    Redis系列-存储篇sorted set主要操作函数小结
    Code First Migrations更新数据库结构的具体步骤
    json文件解析
    go语言文件操作
    docker容器与主机之间的文件复制
    ubuntu16.04 安装docker
    Go语言string,int,int64 ,float之间类型转换方法
  • 原文地址:https://www.cnblogs.com/fulina/p/6163578.html
Copyright © 2020-2023  润新知