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

本文共 5835 字,大约阅读时间需要 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/

你可能感兴趣的文章
Objective-C实现jumpSearch跳转搜索算法(附完整源码)
查看>>
Objective-C实现k nearest neighbours k最近邻分类算法(附完整源码)
查看>>
Objective-C实现k-means clustering均值聚类算法(附完整源码)
查看>>
Objective-C实现k-Means算法(附完整源码)
查看>>
Objective-C实现k-nearest算法(附完整源码)
查看>>
Objective-C实现KadaneAlgo计算给定数组的最大连续子数组和算法(附完整源码)
查看>>
Objective-C实现kahns algorithm卡恩算法(附完整源码)
查看>>
Objective-C实现karatsuba大数相乘算法(附完整源码)
查看>>
Objective-C实现karger算法(附完整源码)
查看>>
Objective-C实现KMP搜索算法(附完整源码)
查看>>
Objective-C实现Knapsack problem背包问题算法(附完整源码)
查看>>
Objective-C实现knapsack背包问题算法(附完整源码)
查看>>
Objective-C实现knapsack背包问题算法(附完整源码)
查看>>
Objective-C实现knight tour骑士之旅算法(附完整源码)
查看>>
Objective-C实现knight Tour骑士之旅算法(附完整源码)
查看>>
Objective-C实现KNN算法(附完整源码)
查看>>
Objective-C实现KNN算法(附完整源码)
查看>>
Objective-C实现KNN算法(附完整源码)
查看>>
Objective-C实现knuth morris pratt(KMP)算法(附完整源码)
查看>>
Objective-C实现knuth-morris-pratt(KMP)算法(附完整源码)
查看>>