博客
关于我
【UE4】C++ 委托、多线程
阅读量:330 次
发布时间:2019-03-04

本文共 5705 字,大约阅读时间需要 19 分钟。

UE4 中委托与任务系统实践

1. 委托机制

委托机制是 UE4 提供的一种强大的功能,允许我们将函数的执行权转移给其他组件或对象。这种机制在游戏开发中非常有用,尤其是在需要扩展或模块化代码时。

1.1 委托类型

委托可以分为多种类型,包括:

  • Object:直接使用 UObject 的成员函数
  • Lambda:使用 lambda 表达式
  • Raw:直接使用函数指针
  • SP:静态函数
  • Static:静态成员函数
  • WeakLambda:弱引用 lambda
  • UFunction:通过 UFunction 类绑定的函数

1.2 委托执行

void UDelegateObject::TestDelegate() {    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__));}

1.3 委托绑定与管理

FTestDelegate& UDelegateMaker::MakeDelegate(EDelegateType Type) {    if (Delegate.IsBound()) {        Delegate.Unbind();    }    switch (Type) {        case EDelegateType::Object:            if (UEObject == nullptr) {                UEObject = NewObject
(); } Delegate.BindUObject(UEObject, &UDelegateObject::TestDelegate); break; }}
void ADelegateInvoker::InvokeDelegate(EDelegateType Type) {    if (Maker == nullptr) {        Maker = NewObject
(); Maker->MakeDelegate(Type).ExecuteIfBound(); } else { Maker->MakeDelegate(Type).ExecuteIfBound(); }}

2. 多线程

多线程编程在游戏开发中非常重要,尤其是在需要同时处理复杂任务时。UE4 提供了丰富的多线程支持工具和功能。

3. 依赖关系结构体

依赖关系结构体用于定义任务之间的依赖关系,确保任务按正确顺序执行。

USTRUCT(BlueprintType) struct FMyTaskItem {    GENERATED_USTRUCT_BODY()public:    UPROPERTY(BlueprintReadWrite)    FString TaskName;    FString TaskName;    FGraphEventRef GraphEvent;    TGraphTask* GraphTask;    FMyTaskItem() :        TaskName(TEXT("NoName")),        GraphEvent(nullptr),        GraphTask(nullptr) {}    FMyTaskItem(FString Name, FGraphEventRef EventRef = FGraphEventRef())        : TaskName(Name),        GraphEvent(EventRef),        GraphTask(nullptr) {}    FMyTaskItem(FString Name, TGraphTask* Task = nullptr)        : TaskName(Name),        GraphEvent(nullptr),        GraphTask(Task) {}    ~FMyTaskItem() {        GraphEvent = nullptr;    }};

4. 任务定义

任务类用于定义任务的具体行为和执行方式。

class FJustPrintTask {    FString TaskName;    TArray
ChildEvents; AActor* TaskOwner;public: FJustPrintTask(FString Name, TArray
Events, AActor* Actor) : TaskName(Name), ChildEvents(Events), TaskOwner(Actor) {} ~FJustPrintTask() {} FORCEINLINE TStatId GetStatId() const { RETURN_QUICK_DECLARE_CYCLE_STAT(FJustPrintTask, STATGROUP_TaskGraphTasks); } static ENamedThreads::Type GetDesiredThread() { return ENamedThreads::AnyThread; } static ESubsequentsMode::Type GetSubsequentsMode() { return ESubsequentsMode::TrackSubsequents; } void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) { UE_LOG(LogTemp, Log, TEXT(__FUNCTION__ " %s:Begin"), *TaskName); for (TGraphTask* Task : ChildEvents) { if (Task) { Task->Unlock(); MyCompletionGraphEvent->DontCompleteUntil(Task->GetCompletionEvent()); } } MyCompletionGraphEvent->DontCompleteUntil(TGraphTask::CreateTask().ConstructAndDispatchWhenReady(TaskName, TaskOwner)); UE_LOG(LogTemp, Log, TEXT(__FUNCTION__ " %s:End"), *TaskName); }}

5. 报告任务

报告任务用于在任务完成时触发特定事件。

class FReportTask {    FString TaskName;    AActor* TaskOwner;public:    FReportTask(FString Name, AActor* Actor) :        TaskName(Name),        TaskOwner(Actor) {}    ~FReportTask() {}    FORCEINLINE TStatId GetStatId() const {        RETURN_QUICK_DECLARE_CYCLE_STAT(FReportTask, STATGROUP_TaskGraphTasks);    }    static ENamedThreads::Type GetDesiredThread() {        return ENamedThreads::GameThread;    }    static ESubsequentsMode::Type GetSubsequentsMode() {        return ESubsequentsMode::TrackSubsequents;    }    void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) {        AMyTaskGraphActor* Actor = Cast
(TaskOwner); if (IsValid(Actor)) { Actor->OnTaskComplete(TaskName); } }}

6. Actor 与蓝图类

Actor 类用于管理任务执行。

UCLASS() class UECPP_API AMyTaskGraphActor : public AActor {    GENERATED_BODY()public:    AMyTaskGraphActor();    FMyTaskItem CreateTask(FString TaskName, const TArray
& Prerequisites, const TArray
& ChildTasks, bool DispatchWhenReady = true); FMyTaskItem CreateTaskPure(FString TaskName, bool DispatchWhenReady = true) { return CreateTask(TaskName, Empty, Empty, DispatchWhenReady); } FMyTaskItem CreateTaskWithPrerequisitesOnly(FString TaskName, const TArray
& Prerequisites, bool DispatchWhenReady = true) { return CreateTask(TaskName, Prerequisites, Empty, DispatchWhenReady); } FMyTaskItem CreateTaskWithChildTasksOnly(FString TaskName, const TArray
& ChildTasks, bool DispatchWhenReady = true) { return CreateTask(TaskName, Empty, ChildTasks, DispatchWhenReady); } UFUNCTION(BlueprintCallable) void FireTask(const FMyTaskItem& Task); UFUNCTION(BlueprintImplementableEvent) void OnTaskComplete(const FString& TaskName);}

7. 任务执行

任务执行需要按照依赖关系顺序完成。

void FJustPrintTask::DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) {    UE_LOG(LogTemp, Log, TEXT(__FUNCTION__ " %s:Begin"), *TaskName);    for (TGraphTask* Task : ChildEvents) {        if (Task) {            Task->Unlock();            MyCompletionGraphEvent->DontCompleteUntil(Task->GetCompletionEvent());        }    }    MyCompletionGraphEvent->DontCompleteUntil(TGraphTask::CreateTask().ConstructAndDispatchWhenReady(TaskName, TaskOwner));    UE_LOG(LogTemp, Log, TEXT(__FUNCTION__ " %s:End"), *TaskName);}

8. Actor 函数实现

void AMyTaskGraphActor::FireTask(const FMyTaskItem& Task) {    if (Task.GraphTask) {        UE_LOG(LogTemp, Log, TEXT("Task[%s] Fire."), *Task.TaskName));        Task.GraphTask->Unlock();    }}

通过以上内容,可以看出 UE4 提供了强大的任务和委托系统,能够有效管理复杂任务流程和依赖关系。

转载地址:http://ibuh.baihongyu.com/

你可能感兴趣的文章
MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
查看>>
MsEdgeTTS开源项目使用教程
查看>>
msf
查看>>
MSSQL数据库查询优化(一)
查看>>
MSSQL数据库迁移到Oracle(二)
查看>>
MSSQL日期格式转换函数(使用CONVERT)
查看>>
MSTP多生成树协议(第二课)
查看>>
MSTP是什么?有哪些专有名词?
查看>>
Mstsc 远程桌面链接 And 网络映射
查看>>
Myeclipse常用快捷键
查看>>
MyEclipse更改项目名web发布名字不改问题
查看>>
MyEclipse用(JDBC)连接SQL出现的问题~
查看>>
mt-datetime-picker type="date" 时间格式 bug
查看>>
myeclipse的新建severlet不见解决方法
查看>>
MyEclipse设置当前行背景颜色、选中单词前景色、背景色
查看>>
Mtab书签导航程序 LinkStore/getIcon SQL注入漏洞复现
查看>>
myeclipse配置springmvc教程
查看>>
MyEclipse配置SVN
查看>>
MTCNN 人脸检测
查看>>
MyEcplise中SpringBoot怎样定制启动banner?
查看>>