虚幻引擎黑板键拾取器(FBlackboardKeySelector)

前言

本文针对C++操作,并且针对在重写行为树组件中任务,装饰器,服务节点需要拾取黑板数据的操作

在虚幻引擎重写行为树中的任务,装饰器,服务节点时,通常需要操作与之关联的黑板中的数据。黑板中的数据获取方式从UBlackboardComponent中可以查到大致可分为两种方式:通过给定FName名称,通过KeyID(FBlackboard::FKey类型)

通过名称相对较好理解,但是通过KeyID,相对来说就麻烦一些,主要需要思考ID到底在哪里来。

在使用官方提供的行为树节点时,我们是能看到官方给定的节点是带有选项方式关联黑板数据,例如截图:

MoveTo任务节点细节面板截图

通过面板直接拾取关联黑板中的数据使得操作更加方便和安全。

源码

从查找源码不难发现官方实现方法。我们可以通过查阅UBTTask_MoveTo源码找到是实现。首先在UBTTask_MoveTo继承了UBTTask_BlackboardBase,在UBTTask_BlackboardBase的头文件中,他添加了成员变量BlackboardKey,这是用来获取黑板数据的关键。源码如下:

1/** blackboard key selector */
2UPROPERTY(EditAnywhere, Category=Blackboard)
3struct FBlackboardKeySelector BlackboardKey;

必要操作

添加完BlackboardKey后,需要重写虚函数InitializeFromAsset,这一部非常重要,否则获取黑板中的属性ID会出问题。

1//头文件中
2/** initialize any asset related data */
3virtual void InitializeFromAsset(UBehaviorTree& Asset) override;
 1//源文件中实现
 2void UBTTask_BlackboardBase::InitializeFromAsset(UBehaviorTree& Asset)
 3{
 4	Super::InitializeFromAsset(Asset);
 5
 6	UBlackboardData* BBAsset = GetBlackboardAsset();
 7	if (BBAsset)
 8	{
 9		BlackboardKey.ResolveSelectedKey(*BBAsset);
10	}
11	else
12	{
13		UE_LOG(LogBehaviorTree, Warning, TEXT("Can't initialize task: %s, make sure that behavior tree specifies blackboard asset!"), *GetName());
14	}
15}

添加类型约束

对于黑板中的数据进行关联拾取,FBlackboardKeySelector类型数据同时提供了类型约束,即只能拾取某些类型数据,注意需要填写在构造函数中。参照UBTTask_MoveTo源码如下:

1// accept only actors and vectors
2BlackboardKey.AddObjectFilter(this, GET_MEMBER_NAME_CHECKED(UBTTask_MoveTo, BlackboardKey), AActor::StaticClass());
3BlackboardKey.AddVectorFilter(this, GET_MEMBER_NAME_CHECKED(UBTTask_MoveTo, BlackboardKey));

对于类型约束,可以添加多种约束。对于对象型数据还可以指针数据的类型。

当存在多种类型拾取,如何区分?

当添加多种约束后如何区分到底拾取的是那种类型?这部分可以通过阅读源码了解,例如在UBTTask_MoveTo中可以找到以下源码:

1if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass())
2{
3    UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID());
4    AActor* TargetActor = Cast<AActor>(KeyValue);
5}
6else if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass())
7{
8    const FVector TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID());
9}

结语

以上就是解决在重写行为树中的任务,装饰器,服务节点时,需要获取黑板数据的方法,通过阅读UBTTask_MoveTo类源码可以获得所有内容。

文章评论