前言
本文针对C++操作,并且针对在重写行为树组件中任务,装饰器,服务节点需要拾取黑板数据的操作
在虚幻引擎重写行为树中的任务,装饰器,服务节点时,通常需要操作与之关联的黑板中的数据。黑板中的数据获取方式从UBlackboardComponent中可以查到大致可分为两种方式:通过给定FName名称,通过KeyID(FBlackboard::FKey类型)
通过名称相对较好理解,但是通过KeyID,相对来说就麻烦一些,主要需要思考ID到底在哪里来。
在使用官方提供的行为树节点时,我们是能看到官方给定的节点是带有选项方式关联黑板数据,例如截图:
MoveTo任务节点细节面板截图
通过面板直接拾取关联黑板中的数据使得操作更加方便和安全。
源码
从查找源码不难发现官方实现方法。我们可以通过查阅UBTTask_MoveTo源码找到是实现。首先在UBTTask_MoveTo继承了UBTTask_BlackboardBase,在UBTTask_BlackboardBase的头文件中,他添加了成员变量BlackboardKey,这是用来获取黑板数据的关键。源码如下:
1
2
3
|
/** blackboard key selector */
UPROPERTY(EditAnywhere, Category=Blackboard)
struct FBlackboardKeySelector BlackboardKey;
|
必要操作
添加完BlackboardKey后,需要重写虚函数InitializeFromAsset,这一部非常重要,否则获取黑板中的属性ID会出问题。
1
2
3
|
//头文件中
/** initialize any asset related data */
virtual void InitializeFromAsset(UBehaviorTree& Asset) override;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//源文件中实现
void UBTTask_BlackboardBase::InitializeFromAsset(UBehaviorTree& Asset)
{
Super::InitializeFromAsset(Asset);
UBlackboardData* BBAsset = GetBlackboardAsset();
if (BBAsset)
{
BlackboardKey.ResolveSelectedKey(*BBAsset);
}
else
{
UE_LOG(LogBehaviorTree, Warning, TEXT("Can't initialize task: %s, make sure that behavior tree specifies blackboard asset!"), *GetName());
}
}
|
添加类型约束
对于黑板中的数据进行关联拾取,FBlackboardKeySelector类型数据同时提供了类型约束,即只能拾取某些类型数据,注意需要填写在构造函数中。参照UBTTask_MoveTo源码如下:
1
2
3
|
// accept only actors and vectors
BlackboardKey.AddObjectFilter(this, GET_MEMBER_NAME_CHECKED(UBTTask_MoveTo, BlackboardKey), AActor::StaticClass());
BlackboardKey.AddVectorFilter(this, GET_MEMBER_NAME_CHECKED(UBTTask_MoveTo, BlackboardKey));
|
对于类型约束,可以添加多种约束。对于对象型数据还可以指针数据的类型。
当存在多种类型拾取,如何区分?
当添加多种约束后如何区分到底拾取的是那种类型?这部分可以通过阅读源码了解,例如在UBTTask_MoveTo中可以找到以下源码:
1
2
3
4
5
6
7
8
9
|
if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Object::StaticClass())
{
UObject* KeyValue = MyBlackboard->GetValue<UBlackboardKeyType_Object>(BlackboardKey.GetSelectedKeyID());
AActor* TargetActor = Cast<AActor>(KeyValue);
}
else if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass())
{
const FVector TargetLocation = MyBlackboard->GetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID());
}
|
结语
以上就是解决在重写行为树中的任务,装饰器,服务节点时,需要获取黑板数据的方法,通过阅读UBTTask_MoveTo类源码可以获得所有内容。