博客
关于我
【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 CONCAT()函数拼接有NULL
查看>>
multiprocessing.Manager 嵌套共享对象不适用于队列
查看>>
multiprocessing.pool.map 和带有两个参数的函数
查看>>
MYSQL CONCAT函数
查看>>
multiprocessing.Pool:map_async 和 imap 有什么区别?
查看>>
MySQL Connector/Net 句柄泄露
查看>>
multiprocessor(中)
查看>>
mysql CPU使用率过高的一次处理经历
查看>>
Multisim中555定时器使用技巧
查看>>
MySQL CRUD 数据表基础操作实战
查看>>
multisim变压器反馈式_穿过隔离栅供电:认识隔离式直流/ 直流偏置电源
查看>>
mysql csv import meets charset
查看>>
multivariate_normal TypeError: ufunc ‘add‘ output (typecode ‘O‘) could not be coerced to provided……
查看>>
MySQL DBA 数据库优化策略
查看>>
multi_index_container
查看>>
mutiplemap 总结
查看>>
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>