介绍
通过UE提供的反射,插件会根据配置生成指定模块和插件下的类,结构体,枚举,以及资源类型。
基础概念
UE和C#两侧的反射类型存在一一对应关系,对于简单类型比较容易理解,针对如UObject,蓝图等此类复杂类型,需要先了解一下UE中Package的概念,推荐UE4的资源管理和[中文直播]第33期 | UE4资产管理基础1 | Epic 大钊。
- C++
- Blueprint
如AActor,会将/Script/Engine.Actor映射为Script.Engine.Actor,规则为去掉首位/,并将/替换为.
如BP_TestReflectionPropertyActor_C,会将/Game/UnitTest/Reflection/BP_TestReflectionPropertyActor.BP_TestReflectionPropertyActor_C映射为Script.Game.UnitTest.Reflection.BP_TestReflectionPropertyActor_C,规则为加上Script/,去掉BP_TestReflectionPropertyActor.,并将/替换为.
数据类型
针对不同的数据类型,有不同的处理方式,分为以下几个大类。
- 基本类型
- 字符串
- 枚举
- 结构体
- UObject
- 模板
- 容器
- 代理
| C++ | C# |
|---|---|
| bool | bool |
| int8 | sbyte |
| int16 | short |
| int32 | int |
| int64 | long |
| uint8 | byte |
| uint16 | ushort |
| uint32 | uint |
| uint64 | ulong |
| float | float |
| double | double |
| C++ | C# |
|---|---|
| FName | Script.CoreUObject.FName |
| FText | Script.CoreUObject.FText |
| FString | Script.CoreUObject.FString |
对于枚举和TEnumAsByte都会被对应到映射关系下的枚举。
示例:枚举
- C++
- C#
UENUM(BlueprintType)
enum ETestEnum
{
TestEnumZero,
TestEnumOne,
TestEnumTwo
};
using Script.CoreUObject;
namespace Script.UnrealCSharpTest
{
[PathName("/Script/UnrealCSharpTest.ETestEnum")]
public enum ETestEnum : byte
{
TestEnumZero = 0,
TestEnumOne = 1,
TestEnumTwo = 2,
}
}
会生成反射变量,StaticStruct,构造函数和析构函数等。
示例:结构体
- C++
- C#
USTRUCT(BlueprintType)
struct FTestStruct
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite)
int32 Value;
};
using Script.Library;
using Script.CoreUObject;
namespace Script.UnrealCSharpTest
{
[PathName("/Script/UnrealCSharpTest.TestStruct")]
public partial class FTestStruct : IStaticStruct, IGarbageCollectionHandle
{
public static UScriptStruct StaticStruct()
{
return UStructImplementation.UStruct_StaticStructImplementation("/Script/UnrealCSharpTest.TestStruct");
}
public FTestStruct() => UStructImplementation.UStruct_RegisterImplementation(this, Utils.GetPathName(GetType()));
~FTestStruct() => UStructImplementation.UStruct_UnRegisterImplementation(GarbageCollectionHandle);
public static bool operator ==(FTestStruct A, FTestStruct B) => UStructImplementation.UStruct_IdenticalImplementation(StaticStruct().GarbageCollectionHandle, A?.GarbageCollectionHandle??nint.Zero, B?.GarbageCollectionHandle??nint.Zero);
public static bool operator !=(FTestStruct A, FTestStruct B) => !UStructImplementation.UStruct_IdenticalImplementation(StaticStruct().GarbageCollectionHandle, A?.GarbageCollectionHandle??nint.Zero, B?.GarbageCollectionHandle??nint.Zero);
public override bool Equals(object Other) => this == Other as FTestStruct;
public override int GetHashCode() => (int)GarbageCollectionHandle;
public int Value
{
get => FPropertyImplementation.FProperty_GetStructInt32PropertyImplementation(GarbageCollectionHandle, __Value);
set => FPropertyImplementation.FProperty_SetStructInt32PropertyImplementation(GarbageCollectionHandle, __Value, value);
}
private static uint __Value = 0;
public nint GarbageCollectionHandle { get; set; }
}
}
会生成反射变量,反射函数,接口函数和StaticClass等。
示例:UObject
- C++
- C#
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "UnitTest/Core/TestInterface.h"
#include "TestReflectionPropertyActor.generated.h"
UCLASS()
class UNREALCSHARPTEST_API ATestReflectionPropertyActor : public AActor, public ITestInterface
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATestReflectionPropertyActor();
public:
UPROPERTY(BlueprintReadWrite)
int32 Int32Value;
};
using Script.Engine;
using Script.CoreUObject;
using Script.Library;
namespace Script.UnrealCSharpTest
{
[PathName("/Script/UnrealCSharpTest.TestReflectionPropertyActor")]
public partial class ATestReflectionPropertyActor : AActor, IStaticClass, ITestInterface
{
public int Int32Value
{
get => FPropertyImplementation.FProperty_GetObjectInt32PropertyImplementation(GarbageCollectionHandle, __Int32Value);
set => FPropertyImplementation.FProperty_SetObjectInt32PropertyImplementation(GarbageCollectionHandle, __Int32Value, value);
}
public new static UClass StaticClass()
{
return UObjectImplementation.UObject_StaticClassImplementation("/Script/UnrealCSharpTest.TestReflectionPropertyActor");
}
private static uint __Int32Value = 0;
}
}
| C++ | C# |
|---|---|
| TScriptInterface | Script.CoreUObject.TScriptInterface`1 |
| TSubclassOf | Script.CoreUObject.TSubclassOf`1 |
| TWeakObjectPtr | Script.CoreUObject.TWeakObjectPtr`1 |
| TLazyObjectPtr | Script.CoreUObject.TLazyObjectPtr`1 |
| TSoftObjectPtr | Script.CoreUObject.TSoftObjectPtr`1 |
| TSoftClassPtr | Script.CoreUObject.TSoftClassPtr`1 |
| TOptional | Script.CoreUObject.TOptional`1 |
| C++ | C# |
|---|---|
| TArray | Script.CoreUObject.TArray`1 |
| TSet | Script.CoreUObject.TSet`1 |
| TMap | Script.CoreUObject.TMap`2 |
单播和多播都会映射为C#中的类,并且提供相关操作函数。
- 单播
- 多播
示例:单播
- C++
- C#
DECLARE_DYNAMIC_DELEGATE_RetVal_TwoParams(FEventReply, FOnPointerEvent, FGeometry, MyGeometry, const FPointerEvent&, MouseEvent);
using System;
using Script.CoreUObject;
using Script.Library;
using Script.SlateCore;
using Script.UMG;
namespace Script.UMG.Widget
{
public class FOnPointerEvent : FDelegate<Func<FGeometry, FPointerEvent, FEventReply>>
{
public FOnPointerEvent() => FDelegateImplementation.FDelegate_RegisterImplementation(this);
~FOnPointerEvent() => FDelegateImplementation.FDelegate_UnRegisterImplementation(GarbageCollectionHandle);
public FEventReply Execute(FGeometry MyGeometry, FPointerEvent MouseEvent)
{
return FDelegateImplementation.FDelegate_Execute3Implementation(GarbageCollectionHandle, MyGeometry, MouseEvent) as FEventReply;
}
}
}
示例:多播
- C++
- C#
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnButtonClickedEvent);
using System;
using Script.CoreUObject;
using Script.Library;
namespace Script.UMG
{
public class FOnButtonClickedEvent : FMulticastDelegate<Action>
{
public FOnButtonClickedEvent() => FMulticastDelegateImplementation.FMulticastDelegate_RegisterImplementation(this);
~FOnButtonClickedEvent() => FMulticastDelegateImplementation.FMulticastDelegate_UnRegisterImplementation(GarbageCollectionHandle);
public void Broadcast()
{
FMulticastDelegateImplementation.FMulticastDelegate_Broadcast0Implementation(GarbageCollectionHandle);
}
}
}