Ue4C++编程------AI与c++(三)

    上文中我们重写了Possess函数,在possess函数中,运行我们的行为树,既然有Possess肯定就有UnPossess啦,因此,我们需要重写UnPossess函数,在该函数中,停止运行我们的行为树,如下所示:

void AAIBlogController::UnPossess()
{
	Super::UnPossess();
	if (BehaviorTreeCompo != nullptr)
	{
		BehaviorTreeCompo->StopTree(EBTStopMode::Safe); // 停止运行行为树
	}
}

    接下来就要修改我们的AICharacter了,还记得我们为AICharacter添加了一个PawnSenceComponent吗?该组件是用来寻找敌人的,使我们的AI有视力,我们需要为该组件绑定函数,当看到敌人时,应该怎么做,显然。在我们这里,在看到敌人时,就更新我们的黑板数据,使我们的AI能知道移动到哪里去。通过查阅ue4的api,知道我们有一个OnSeePawn的代理,因此需要为该代理绑定函数。如下所示:

	UFUNCTION()
	void HaveSeePawn(APawn* Pawn);

    在BeginPlay中,绑定HaveSeePawn,如下所示:

void AAIBlogCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	if (Sight != nullptr)
	{
		Sight->OnSeePawn.AddDynamic(this, &AAIBlogCharacter::HaveSeePawn);
	}
}

    显然,在我们的HaveSeePawn函数中,应该根据我们看到的pawn,获得它的位置,从而根据其位置,来设置我们的黑板数据的值,查阅api,发现只有UBlackBoradComponent才有set值的函数,因此,修改我们的成员,如下所示:

public:
	//class UBlackboardData* HeroData;
	class UBlackboardComponent* HeroData;

    修改我们的possess函数,如下所示:

void AAIBlogController::Possess(APawn* InPawn)
{
	AAIBlogCharacter* AIC = Cast<AAIBlogCharacter>(InPawn);
	if (AIC == nullptr)
	{
		return;
	}

	Super::Possess(InPawn);
	
	if (BehaviorTreeCompo != nullptr)
	{
		if (BehaviorTree != nullptr)
		{
			BehaviorTreeCompo->StartTree(*BehaviorTree); // 运行行为树
			//AIC->HeroData = BehaviorTree->BlackboardAsset; // 设置黑板资源,方便以后更新黑板资源成员数据
			if (AIC->HeroData != nullptr)
			{
				AIC->HeroData->InitializeBlackboard(*BehaviorTree->BlackboardAsset); // 初始化
			}
		}
	}
}

    接下来在HaveSeePawn中,就可以更新我们的值啦,需要注意的是,字段名字一定要与黑板资源上的一致,如下所示:

void AAIBlogCharacter::HaveSeePawn(APawn* Pawn)
{
	ABlogProjectCharacter* Player = Cast<ABlogProjectCharacter>(Pawn);

	if (Player != nullptr)
	{
		FVector Location = Player->GetActorLocation(); // 获取目标的位置,这是世界坐标
		if (HeroData != nullptr)
		{
			HeroData->SetValueAsVector("TargetLocation", Location); // 注意,这里的Location字段要和黑板资源里的一致
		}
	}
}

    

    行为树的节点那些就留到下文再讲吧。该文就到这里啦。

    

猜你喜欢

转载自blog.csdn.net/li2818/article/details/80834260