博客
关于我
【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/

你可能感兴趣的文章
MySQL 8.0 恢复孤立文件每表ibd文件
查看>>
MySQL 8.0开始Group by不再排序
查看>>
mysql ansi nulls_SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 什么意思
查看>>
multi swiper bug solution
查看>>
MySQL Binlog 日志监听与 Spring 集成实战
查看>>
MySQL binlog三种模式
查看>>
multi-angle cosine and sines
查看>>
Mysql Can't connect to MySQL server
查看>>
mysql case when 乱码_Mysql CASE WHEN 用法
查看>>
Multicast1
查看>>
mysql client library_MySQL数据库之zabbix3.x安装出现“configure: error: Not found mysqlclient library”的解决办法...
查看>>
MySQL Cluster 7.0.36 发布
查看>>
Multimodal Unsupervised Image-to-Image Translation多通道无监督图像翻译
查看>>
MySQL Cluster与MGR集群实战
查看>>
multipart/form-data与application/octet-stream的区别、application/x-www-form-urlencoded
查看>>
mysql cmake 报错,MySQL云服务器应用及cmake报错解决办法
查看>>
Multiple websites on single instance of IIS
查看>>
mysql CONCAT()函数拼接有NULL
查看>>
multiprocessing.Manager 嵌套共享对象不适用于队列
查看>>
multiprocessing.pool.map 和带有两个参数的函数
查看>>