怕有些朋友不知道教程指的是哪一个,我在这里把教程的网址贴出来:https://www.bilibili.com/video/BV1nU4y1X7iQ?p=1
这一章开始进入电脑玩家逻辑的编写,因为是第一次接触,所以老师也没有讲什么很难的问题,这里还是老样子,直接上C++的代码
SAICharacter.h
这个对象类把输入给删除了,因为电脑对象不需要我们的输入以及输入事件绑定啥的。然后把相应的cpp文件的相应的函数删除就好。
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SAICharacter.generated.h"
UCLASS()
class ACTIONROGUELIKE_API ASAICharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ASAICharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
然后是SAIController,我看完这一章后对这个controller的理解就是:用来运行我们所选择的行为树,同时给我们的黑板上的变量赋一个初值。
SAIController.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AIController.h"
#include "AIModule/Classes/BehaviorTree/BehaviorTree.h"
#include "SAIController.generated.h"
/**
*
*/
UCLASS()
class ACTIONROGUELIKE_API ASAIController : public AAIController
{
GENERATED_BODY()
//行为树
UPROPERTY(EditDefaultsOnly)
class UBehaviorTree* BehavioutTree;
protected:
virtual void BeginPlay() override;
};
SAIController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "AI/SAIController.h"
#include "Kismet/GameplayStatics.h"
#include "BehaviorTree/BlackboardComponent.h"
void ASAIController::BeginPlay()
{
Super::BeginPlay();
//运行我们指定的行为树
RunBehaviorTree(BehavioutTree);
//gamestatics来获取我们的主玩家
APawn* MyPawn = UGameplayStatics::GetPlayerPawn(this,0);
if (ensure(MyPawn))
{
//给黑板内的变量赋初值
GetBlackboardComponent()->SetValueAsVector("MoveToLocation", MyPawn->GetActorLocation());
GetBlackboardComponent()->SetValueAsObject("TargectActor", MyPawn);
}
}
再之后就是行为树的服务函数了,从UBTServices这个基类派生出来,说白了就是在蓝图编辑器里头写行为树的时候,你右键找‘服务’那一项下面可以找到我们自定义的服务函数。
SBTService_CheckAttackRange.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/BTService.h"
#include "SBTService_CheckAttackRange.generated.h"
/**
*
*/
UCLASS()
class ACTIONROGUELIKE_API USBTService_CheckAttackRange : public UBTService
{
GENERATED_BODY()
//黑板的属性,在蓝图编辑器内指定
protected:
UPROPERTY(EditAnywhere,Category="AI")
FBlackboardKeySelector AttackRangeKey;
//重写父类的函数
protected:
virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
};
SBTService_CheckAttackRange.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "AI/SBTService_CheckAttackRange.h"
#include "AIModule/Classes/BehaviorTree/BlackboardComponent.h"
#include "AIModule/Classes/BehaviorTree/BehaviorTreeTypes.h"
#include "AIModule/Classes/AIController.h"
void USBTService_CheckAttackRange::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
//检查ai和玩家间的距离
UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent();
if (ensure(BlackboardComp))
{
AActor* TargetActor = Cast<AActor>(BlackboardComp->GetValueAsObject("TargetActor"));
if (ensure(TargetActor))
{
AAIController* MyController = OwnerComp.GetAIOwner();
if (ensure(MyController))
{
APawn* AIPawn = MyController->GetPawn();
if (ensure(AIPawn))
{
float DistanceTo = FVector::Distance(TargetActor->GetActorLocation(), AIPawn->GetActorLocation());
bool bWithinRange = DistanceTo < 2000.0f;
bool bHasLineSight = false;
if (bWithinRange)
{
bHasLineSight = MyController->LineOfSightTo(TargetActor);
}
BlackboardComp->SetValueAsBool(AttackRangeKey.SelectedKeyName , (bWithinRange&&bHasLineSight));
}
}
}
}
}
我们写的这个service在蓝图里头长这样:
可以看到有个Attack Range Key,这个就是我们在.h里头定义的那个blackboardkeyselector的变量。剩余的蓝图的内容以及创建对象绑定动画,创建C++的蓝图类啥的我就不在这里赘述了,教程讲的非常明确。