UE4学习笔记(函数声明周期,委托与事件,反射机制)

本文由用户“yongkim”分享发布 更新时间:2021-05-02 05:41:57 举报文档

以下为《UE4学习笔记(函数声明周期,委托与事件,反射机制)》的无排版文字预览,完整格式请下载

下载前请仔细阅读文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

函数声明周期:

GameInstance::Init //创建世界 World 将World保存进GameInstance中的结构体WorldContext中

LevelScriptActor::Construct //创建Level,LevelScriptActor

MyActor::Construct //MyActor是已经存在场景中的Actor(即编辑器模式下创建的)

GameMode::Construct //WorldSetting绑定的框架运行

MyActor::PostInitializeComponents //Actor所有组件初始化(UActorComponent::InitializeComponent)调用完后调用的函数

LevelScriptActor::PostInitializeComponents

GameMode::PostInitializeComponents

Controller::Construct

Controller::PostInitializeComponents

HUD::NativeConstruct

HUD::PostInitializeComponents

Character::Construct

Character::PostInitializeComponents

MyActor::BeginPlay

GameMode::BeginPlay

LevelScriptActor::BeginPlay

Controller::BeginPlay

HUD::BeginPlay

UserWidget::Construct

UserWidget::Initialize (相当于PostInitializeComponents)

Character::BeginPlay

Controller::Tick

MyActor::Tick

LevelScriptActor::Tick

Character::Tick

HUD::Tick

UserWidget::Tick ?

?

Tips

AActor::PreInitializeComponents //Actor组件初始化前调用的函数

->UActorComponent::InitializeComponent //Actor组件初始化

->Aactor::PostInitializeComponnet //Actor所有组件初始化调用完后调用的函数

?

总结:

Construct->PostInitializeComponents->BeginPlay->Tick

委托与事件

单播与多播

http://api.unrealengine.com/CHN/Programming/UnrealArchitecture/Delegates/index.html

?

利用委托可以泛型但类型安全的方式在C++对象上调用成员函数。可使用委托动态绑定到任意对象的成员函数,然后在该对象上调用函数,即使调用程序不知对象类型也可进行操作

复制委托对象绝对安全。可利用值传递委托,但其须在堆上分配内存,因此通常并不推荐此操作。应尽量固定利用引用传递委托。

同时支持单某某和多投射委托,及可安全序列化到硬盘的“动态”委托。

单某某

多投射

事件

动态(UObject, serializable)

声明委托

使用提供的声明宏之一来声明委托。所用宏由要绑定到委托的函数的签名决定。系统预定义各种泛型函数签名组合,可在从中声明委托类型、填充返回值及所需参数类型的类型名。当前支持以下使用任意组合的委托签名:

返回值的函数

最多4个“负载”变量

最多8个函数参数

声明为“const”的函数

使用此表格查找要用于声明委托的生命宏。

函数签名

声明宏



void Function()

DECLARE_DELEGATE( DelegateName )



void Function( )

DECLARE_DELEGATE_OneParam( DelegateName, Param1Type )



void Function( , )

DECLARE_DELEGATE_TwoParams( DelegateName, Param1Type, Param2Type )



void Function( , , ...)

DECLARE_DELEGATE_Params( DelegateName, Param1Type, Param2Type, ...)



 Function()

DECLARE_DELEGATE_RetVal( RetValType, DelegateName )



 Function( )

DECLARE_DELEGATE_RetVal_OneParam( RetValType, DelegateName, Param1Type )



 Function( , )

DECLARE_DELEGATE_RetVal_TwoParams( RetValType, DelegateName, Param1Type, Param2Type )



 Function( , , ...)

DECLARE_DELEGATE_RetVal_Params( RetValType, DelegateName, Param1Type, Param2Type, ...)



同时还提供以上宏的变体,用于多投射、动态和包裹委托:

DECLARE_MULTICAST_DELEGATE...

DECLARE_DYNAMIC_DELEGATE...

DECLARE_DYNAMIC_MULTICAST_DELEGATE...

DECLARE_DYNAMIC_DELEGATE...

DECLARE_DYNAMIC_MULTICAST_DELEGATE...

委托签名声明可存在于全局作用域、在命名空间,甚至是类声明中(但无法存在于函数主体中)。

参见%Programming/UnrealArchitecture/Delegates/Dynamic:title% and?多播委托,了解声明此类委托的更多相关信息。

绑定委托

委托系统理解某些类型的对象,使用此类对象时将启用附加功能。将委托绑定到UObject或共享指针类的成员,委托系统可保留对该对象的弱引用,因此对象在委托下方被销毁时,可通过调用?IsBound()?或?ExecuteIfBound()?函数进行处理。注意各类受支持对象的特殊绑定语法。

函数

描述



Bind()

绑定到现有委托对象。



BindStatic()

绑定原始C++指针全局函数委托。



BindRaw()

绑定原始C++指针委托。原始指针不使用任何类型的引用,因此如对象在委托下方被删除,引用原始指针可能不安全。需谨慎调用Execute()!



BindSP()

绑定基于指针的共享成员函数委托。共享指针委托会保留对对象的弱引用。可使用?ExecuteIfBound()?进行调用。



BindUObject()

绑定基于UObject的成员函数委托。UObject委托会保留对对象的弱引用。可使用?ExecuteIfBound()?进行调用。



UnBind()

取消绑定此委托。



参见?DelegateSignatureImpl.inl(位于?..\UE4\Engine\Source\Runtime\Core\Public\Templates\),了解此类函数的变体、参数和实现。

负载数据

绑定到委托时,可同时传递负载数据。其为调用时被直接传到绑定函数的任意变量。此操作十分有用,利用其可在绑定时将参数存储在委托内。所有委托类型(除“动态”外)均自动支持负载变量。此范例将两个自定义变量(一个布尔,一个int32)传递到委托。之后调用该委托时,此类参数将被传到绑定函数。须始终接受委托类型参数后的额外变量参数。

MyDelegate.BindRaw( &MyFunction, true, 20 );

执行委托

通过调用委托的?Execute()?函数执行绑定到委托的函数。执行前须检查委托是否已绑定。此操作是为了使代码更安全,因为有时委托可能含有未初始化且被后续访问的返回值和输出参数。执行未绑定的委托在某些情况下确实可能导致内存混乱。可调用?IsBound()?检查是否可安全执行委托。同时,对于无返回值的委托,可调用ExecuteIfBound(),但需注意输出参数可能未初始化。

?

执行函数

描述



Execute()

?



ExecuteIfBound()

?



IsBound()

?



参见多播委托,了解执行多投射委托的相关细节。

用法示例

假设类拥有可在任何地方随意调用的方法:

class FLogWriter { void WriteToLog( FString ); };

要调用WriteToLog函数,需创建该函数签名的委托类型。为此,首先需使用以下宏声明委托。例如,以下是一个简单的委托类型:

DECLARE_DELEGATE_OneParam( FStringDelegate, FString );

此将创建名为“FStringDelegate”的委托类型,该类型使用“FString”类型的单个参数。

此为在类中使用此“FStringDelegate”的方法范例:

class FMyClass { FStringDelegate WriteToLogDelegate; };

利用此操作,类可保有指向任意类中的方法的指针。该类唯一真正了解的信息就是,此委托是其的函数签名。

如要分配委托,现在只需创建委托类的实例,将拥有该方法的类作为模板参数传递。同时还需传递对象的实例和方法的实际函数地址。因此,现在需创建“FLogWriter”类的实例,然后创建改对象实例"WriteToLog"方法的委托。

TSharedRef< FLogWriter > LogWriter( new FLogWriter() );

WriteToLogDelegate.BindSP( LogWriter, &FLogWriter::WriteToLog );

此操作可将委托动态绑定到类的方法!很简单,对吧?

注意:绑定到的对象由共享指针拥有,因此?BindSP?的SP部分代表共享指针。此外,还有不同对象类型的版本,例如BindRaw()和BindUObject()。

FMyClass现在可调用“WriteToLog”方法,甚至无需了解“FLogWriter”类的任何信息!要调用委托,只需使用“Execute()”方法:

WriteToLogDelegate.Execute( TEXT( "Delegates are spiffy!") );

如将函数绑定到网络前调用Execute(),将触发断言:多数情况下,建议进行以下操作:

WriteToLogDelegate.ExecuteIfBound( TEXT( "Only executes if a function was bound!") );

?

?

?

?

?

?

?

?

?

?

?

普通的动态

http://api.unrealengine.com/CHN/Programming/UnrealArchitecture/Delegates/Dynamic/index.html

?

动态代理可以进行序列化,可以通过名称查找它们函数,其执行速度比常规代理慢。

声明动态代理

动态代理的声明方式和声明标准代理一样,只是它们使用针对于动态代理的宏变种。

声明宏

描述



DECLARE_DYNAMIC_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个动态代理。



DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个动态的多播代理。



DECLARE_DYNAMIC_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个封装的动态代理。



DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个封装的动态多播代理。



动态代理绑定

辅助宏

描述



BindDynamic( UserObject, FuncName )

在动态代理上调用BindDynamic()的辅助宏。自动生成函数名称字符串。



AddDynamic( UserObject, FuncName )

在动态多播代理上调用AddDynamic()的辅助宏。自动生成函数名称字符串。



RemoveDynamic( UserObject, FuncName )

在动态多播代理上调用RemoveDynamic()的辅助宏。自动生成函数名称字符串。



执行动态代理

[INCLUDE:Programming/UnrealArchitecture/Delegates#ExecutingDelegates]

封装的动态代理

动态代理声明时可以具有一个执行该代理的封装器代理方法。

声明宏

描述



DECLARE_DYNAMIC_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个封装的动态代理。



DECLARE_DYNAMIC_MULTICAST_DELEGATE[_Const, _RetVal, etc.]( DelegateName )

创建一个封装的动态多播代理。





反射机制(重点)

UCLASS()?

告知虚幻引擎生成类的反射数据。类必须派生自 UObject。

?

USTGENERATED_BODYRUCT()?

告知虚幻引擎生成结构体的反射数据。

?

()?

UE4 使用它替代为类型生成的所有必需样板文件代码。

?

UPROPERTY()?

使 UCLASS 或 USTRUCT 的成员变量可用作 UPROPERTY。UPROPERTY 用途广泛。它允许变量被复制、被序列化,并可从蓝图中进行访问。垃圾回收器还使用它们来追踪对 UObject 的引用数。

?

UFUNCTION()?

使 UCLASS 或 USTRUCT 的类方法可用作 UFUNCTION。UFUNCTION 允许类方法从蓝图中被调用,并在其他资源中用作 RPC。

?

UENUM()

创建可以被蓝图调用的enum反射。该类必须继承自uint8。

UENUM(Blueprintable,BlueprintType)

STRUCT(Blueprintable,BlueprintType)

UCLASS(Blueprintable,BlueprintType)

Blueprintable: 可以用蓝图继承该类

BlueprintType: 在其他蓝图中可以把这个继承蓝图类当成一个变量类型

添加了BlueprintType的枚举,结构体,Class 才能在DataTable识别出来

?

官网:: http://api.unrealengine.com/CHN/Programming/Introduction/index.html

?

?

?

?

UPROPERTY/UFUNCTION

EditAnywhere:能被编辑,EditAnywhere的范围是本类蓝图Details面板 以及 放入场景中的Actor?的Details面板

EditDefaultsOnly: 只能在蓝图Details面板中编辑(只能更改蓝图Details面板),游戏运行过程中不能更改

EditInstanceOnly: 只有在拖拽到场景种的的编辑界面(只能更改实例Details面板)

?

VisibleAnywhere:能被任何地方显示(无法被编辑)

?

BlueprintReadOnly:在蓝图中可get

BlueprintReadWrite:在蓝图中可set也可get

?

private:

UPROPERTY(BlueprintGetter = GetGenerateOverlapEvents,BlueprintSetter = SetGenerateOverlapEvents)

uint8 bGenerateOverlapEvents : 1;



?

?

BlueprintAssignable: 只用来修饰委托变量,在蓝图种实现委托事件

?

?

Replicated:属性网络间可复制

ReplicatedUsing:属性除了可以网络复制外,当属性值发生改变时可以触发一个函数,例如:

UPROPERTY(ReliabledUsing=OnMyFunction)

int Num;

UFUNCTION()

void OnMyFunction(var OldVar); //要加UFUNCTION()

Reliable:函数网络间进行复制,并会忽略带宽或网络错误而被确保送达。仅在与客户端或服务器共同使用时可用

UnReliable:函数网络间进行复制,但可能会由于带宽限制或网络错误而传送失败。仅在与客户端或服务器一起使用时有效

?

WithValidation:声明一个名为与main函数相同的附加函数,但将_Validation添加到最后。该函数采用相同的参数,并返回一个布尔值来指示是否应该继续调用主函数

?

Instanced:

实例对象 例如:UPROPERTY(Instanced)

Transient:

暂存,临时存在 例如:UPROPERTY(Transient)

?

Server:此函数仅在服务器上执行。提供一个名称为[FunctionName]_Implementation的函数主体,而不是[FunctionName]; 自动生成的代码将包含一个转换程序来在需要时调用实现方法

Client:此函数仅在该函数从属对象所从属的客户端上执行。提供一个名称为[FunctionName]_Implementation的函数主体,而不是[FunctionName]; 自动生成的代码将包含一个转换程序来在需要时调用实现方法

?

CallInEditor:函数可以在编辑器中通过详细信息面板中的按钮在选定实例中调用

BlueprintCallable: 蓝图可以调用C++方法

meta = (WorldContext = "Obj", CallableWithoutWorldContext):静态函数调用省略UObject* Obj参数

BlueprintImplementa 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 String("xyz123");

FunThreeParam.Count = 675;

//UFunction* Function=SrcObj->FindFunctionChecked(FName("UFunThree"));

//SrcObj->ProcessEvent(Function,FunThreeParam);

SrcObj->ProcessEvent(FunThree, &FunThreeParam); //执行委托

//获取返回值地址

uint8* RetValPtr = (uint8*)&FunThreeParam + FunThree->ReturnValueOffset;

//通过返回值地址 得到返回值所对应的值

int32* RetVal=(int32*)RetValPtr;

DEBUG("ASrcActor->UFunThree Return Value: "+FString::FromInt(*RetVal)+" FunThreeParam.Count: "+FString::FromInt(FunThreeParam.Count));

}

}

[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。

  1. 《计算机专业英语》期末考试试卷
  2. LaTeX画神经网络图
  3. 办公桌面述职报告PPT模板
  4. RWAC期末考试指南
  5. HEC-RAS 训练手册
  6. 橙色长阴影工作汇报PPT模板
  7. 英语周末练习
  8. Flotherm瞬态分析
  9. 壹课空灵ppt模板 (20)
  10. 03-土地利用规划图-Model
  11. A--Unit 9 知识点 课时练习(无答案)
  12. F6 日期
  13. SBR背诵总结 完整版
  14. Unit3Myschoolcalendar
  15. 八年级上册英语unit6课件
  16. 2014人教版八年级上册英语unit6SectionA(1a-1c)课件
  17. +++罗兰贝格PPT模板-436页(绝对经典!)
  18. 美赛指南中英文对照
  19. spy band six
  20. 个人简历ppt模板

以上为《UE4学习笔记(函数声明周期,委托与事件,反射机制)》的无排版文字预览,完整格式请下载

下载前请仔细阅读上面文字预览以及下方图片预览。图片预览是什么样的,下载的文档就是什么样的。

图片预览