UnrealEngine是一個(gè)非常強(qiáng)大的引擎,UE4基于DirectX11哥捕,擁有新的材料流水線(xiàn)牧抽、藍(lán)圖視覺(jué)化腳本、直觀(guān)藍(lán)圖調(diào)試遥赚、內(nèi)容瀏覽器、人物動(dòng)畫(huà)阐肤、Matinee影院級(jí)工具集凫佛、后期處理效果、熱重載孕惜、模擬與沉浸式視角愧薛、實(shí)時(shí)游戲預(yù)覽、AI人工智能衫画、音頻毫炉、中間件集成等一系列全新特性。
下面是用C++結(jié)合藍(lán)圖實(shí)現(xiàn)一個(gè)簡(jiǎn)單的AI功能削罩。效果如下圖
首先創(chuàng)建一個(gè)C++的第三人稱(chēng)工程瞄勾,UE4的工程有很多類(lèi)型,我們可以根據(jù)自己的需要選擇弥激。
然后新建需要的C++文件进陡,包括AIPatrol、AIPatrolController微服、AI巡邏的目標(biāo)點(diǎn)AITargetPoint趾疚,類(lèi)型分別為Character、Controller以蕴、TargetPoint糙麦。
將上述三個(gè)文件擴(kuò)展成藍(lán)圖,這樣C++和藍(lán)圖可以結(jié)合起來(lái)丛肮,比較方便的實(shí)現(xiàn)一些功能赡磅。
新建BehaviorTree、Blackboard腾供。行為樹(shù)用來(lái)實(shí)現(xiàn)AI的邏輯仆邓。
![T98AAKVRE6
]OVK5(AWG0A.png](http://upload-images.jianshu.io/upload_images/1765742-312a11011d4cc53f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)在AIPatrol上加BehaviorTree:
UPROPERTY(EditAnywhere,Category=AI)//add behavior to character
class UBehaviorTree* BehaviorTree;
- 配置character的參數(shù)
![($$_]V}CV$-GAEQ5IIO7MOE.png](http://upload-images.jianshu.io/upload_images/1765742-ad8ce6fb1d799c49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- AIPatrolController
.h文件:
/*behavior tree component*/
UBehaviorTreeComponent* BehaviorComp;
/*Our blackboard component*/
UBlackboardComponent* BlackboardComp;
/*Blackboard keys*/
UPROPERTY(EditDefaultsOnly, Category = AI)
FName LocationToGoKey;
UPROPERTY(EditDefaultsOnly, Category = AI)
FName PlayerKey;
//store all TargetPoints
TArray<AActor*> PatrolPoints;
virtual void Possess(APawn* Pawn) override;
public:
AAIPatrolController();
void SetPlayerCaught(APawn* Pawn);//caught:捕捉
/*Inline getter functions*/
FORCEINLINE UBlackboardComponent* GetBlackboardComp() const { return BlackboardComp; }
FORCEINLINE TArray<AActor* > GetPatrolPoints() const { return PatrolPoints; }
.cpp文件:
AAIPatrolController::AAIPatrolController()
{
/*initialize blackboard and behavior tree*/
BehaviorComp = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorComp"));
BlackboardComp = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComp"));
/*Initialize blackboard keys*/
PlayerKey = "Target";
LocationToGoKey = "LocationToGo";
}
void AAIPatrolController::SetPlayerCaught(APawn* MyPawn)
{
if (BlackboardComp)
{
BlackboardComp->SetValueAsObject(PlayerKey, MyPawn);
}
}
void AAIPatrolController::Possess(APawn* MyPawn)
{
Super::Possess(MyPawn);
/*Get reference to the character*/
AAIPatrol* AICharacter = Cast<AAIPatrol>(MyPawn);
if (AICharacter)
{
if (AICharacter->BehaviorTree->BlackboardAsset)
{
BlackboardComp->InitializeBlackboard(*(AICharacter->BehaviorTree->BlackboardAsset));
}
/*Populate patrol point array*/
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AAIpPatrolPoint::StaticClass(), PatrolPoints);
BehaviorComp->StartTree(*AICharacter->BehaviorTree);
}
}
- 玩家被抓住的方法:
AIPatrolController:
void AAIPatrolController::SetPlayerCaught(APawn* MyPawn)//玩家被抓住
{
if (BlackboardComp)
{
BlackboardComp->SetValueAsObject(PlayerKey, MyPawn);//給玩家添加key值
}
}
AIPatrol:
AAIPatrol::AAIPatrol()
{
//Initialize senses
/**UPawnSensingComponent :
* SensingComponent encapsulates(封裝) sensory(感知) (ie sight and hearing) settings and functionality for an Actor,
* allowing the actor to see/hear Pawns in the world. It does nothing on network clients.
*/
PawnSensingComp = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("PawnSensingComp"));
PawnSensingComp->SetPeripheralVisionAngle(90.0f);
}
// Called when the game starts or when spawned
void AAIPatrol::BeginPlay()
{
Super::BeginPlay();
if (PawnSensingComp)
{
/** OnSeePawn : Delegate to execute when we see a Pawn. */
PawnSensingComp->OnSeePawn.AddDynamic(this, &AAIPatrol::OnplayerCaught);
}
}
void AAIPatrol::OnplayerCaught(APawn* Pawn)
{
/*Get a reference to the palyer controller*/
AAIPatrolController* AIController = Cast<AAIPatrolController>(GetController());
if (AIController)
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("You having been caught!"));
AIController->SetPlayerCaught(Pawn);
}
}
* 創(chuàng)建BTTask的C++文件鲜滩,命名為BTSelectPatrolPoint。注意节值,這時(shí)要在Source文件夾中找到ProjectName.Build.cs文件徙硅,添加GameplayTasks到PublicDependencyModuleName中。.build.cs文件是編譯文件搞疗,位于游戲性模塊的根目錄中嗓蘑,它定義了UnrealBuildTool編譯該模塊時(shí)要使用的一些信息。
BTTask:
EBTNodeResult::Type UBTSelectPatrolPoint::ExecuteTask(UBehaviorTreeComponent & OwnerComp, uint8 * NodeMemory)
{
//get AIPatrolController
AAIPatrolController* AICon = Cast<AAIPatrolController>(OwnerComp.GetAIOwner());
// check the get is successful
if (AICon)
{
//Get Blackboard Component
UBlackboardComponent* BlackboardComp = AICon->GetBlackboardComp();
// get patrolPoint
AAIpPatrolPoint* CurrentPoint = Cast<AAIpPatrolPoint>(BlackboardComp->GetValueAsObject("LocationToGo"));
TArray<AActor*> AvailablePatrolPoints = AICon->GetPatrolPoints();
AAIpPatrolPoint* NextPatrolPoint = nullptr;
// set NextPatrolPoint
if (AICon->CurrentPatrolPoint != AvailablePatrolPoints.Num() - 1)
{
NextPatrolPoint = Cast<AAIpPatrolPoint>(AvailablePatrolPoints[++AICon->CurrentPatrolPoint]);
}
else
{
NextPatrolPoint = Cast<AAIpPatrolPoint>(AvailablePatrolPoints[0]);
AICon->CurrentPatrolPoint = 0;
}
// set blackboard keyValue
BlackboardComp->SetValueAsObject("LocationToGo", NextPatrolPoint);
return EBTNodeResult::Succeeded;
}
return EBTNodeResult::Failed;
}
- 將BP_AIPatrol放入場(chǎng)景匿乃,擺放好BP_AIPatrolPoints桩皿,即AI 要走的路徑,編輯BehaviorTree幢炸。
BehaviorTree的思路是首先執(zhí)行BTSelectPatrolPoint泄隔,如果沒(méi)有找到目標(biāo),就move to key值為L(zhǎng)ocationToGo的點(diǎn)宛徊,如果找到了Target佛嬉,就移動(dòng)到Target處,然后在target處停留1秒闸天。
- 最后暖呕,添加自動(dòng)尋路組件NavMeshBoundsVolume,這樣AI在尋路過(guò)程中就會(huì)自動(dòng)繞開(kāi)障礙物苞氮。