基于C++代码的UE4学习(三十九)——为AI增加感官(视觉与听觉)

 

为AI增加感官(视觉与听觉)需要用到UPawnSensingComponent,需要引入头文件#include "Perception/PawnSensingComponent.h"

在Enemy类中增加感官组件,并增加两个FSciptDelegate,用于后面代理视觉与听觉的方法。

1     FScriptDelegate SightDelegate;
2     FScriptDelegate HearDelegate;
3 
4     UPROPERTY(VisibleAnywhere, Category = "AI | PawSensing")
5     class UPawnSensingComponent* Sense;

 

设置视觉范围,半径,是否视觉回调,是否只看见玩家角色,设置最小听觉阈值,设置最大范围听觉阈值,是否听觉回调,最大听觉年龄。

并设置好两个代理所绑定的方法,当AI听见与看见的时候就回执行这俩方法。

 

 1     //UPawnSensingComponent
 2     Sense = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("Sense"));
 3     Sense->bSeePawns = true;
 4     Sense->SetPeripheralVisionAngle(60);
 5     Sense->SightRadius = 500.0f;
 6     Sense->bOnlySensePlayers = true;
 7 
 8     Sense->HearingThreshold = 100.0f;
 9     Sense->LOSHearingThreshold = 2000.0f;
10     Sense->bHearNoises = true;
11     Sense->HearingMaxSoundAge = 1.0;
12 
13     Sense->SetSensingInterval(0.5f);
14     SightDelegate.BindUFunction(this, "SeeAndChangeBoard");
15     HearDelegate.BindUFunction(this, "HearAndChangeBoard");
16 }

 

 

 1 void AEnemy::BeginPlay()
 2 {
 3     Super::BeginPlay();
 4     UClass* Anima = LoadClass<UAnimInstance>(NULL,TEXT("AnimBlueprint'/Game/Mannequin/Animations/ThirdPerson_AnimBP.ThirdPerson_AnimBP_C'"));
 5     skeletal->SetAnimInstanceClass(Anima);
 6 
 7     //Binding Delegate
 8     Sense->OnSeePawn.Add(SightDelegate);
 9     Sense->OnHearNoise.Add(HearDelegate);
10 }

 

 

OnSeePawn是当AI看见玩家时候该执行什么代理。同理OnHearNoise。

执行看见玩家时候的代理方法如下:

 

 1 void AEnemy::SeeAndChangeBoard(APawn* pawn)
 2 {
 3     AAI_MyProject16Character* PlayerPawn = Cast<AAI_MyProject16Character>(pawn);
 4     AMyAIController* EnemyController = Cast<AMyAIController>(GetController());
 5 
 6     if (Sense->CouldSeePawn(PlayerPawn)) {
 7         if (Sense->HasLineOfSightTo(PlayerPawn)) {
 8             if (EnemyController) {
 9                 EnemyController->myBoard->SetValueAsObject("Target", PlayerPawn);
10                 EnemyController->myBoard->SetValueAsBool("isSeen", true);
11                 //GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, "Seen the pawn and UpdateBlackboard!");
12             }
13         }
14     }
15 }

 

该方法需要传入一个Pawn类对象指针,不能忘。

且在if语句中通过Sense调用CouldSeePawn和HasLineOfSightTo方法来判断他AI是否看到了玩家,是否有障碍阻挡。

运行此方法时候,会对黑板的值进行修改,这里在黑板增加一个bool类型数据,起名isSeen。

 

 

执行听见玩家时候的代理方法如下:

 

 1 void AEnemy::HearAndChangeBoard(APawn* PawnInstigator, const FVector&Location, float Volume)
 2 {
 3     AAI_MyProject16Character* PlayerPawn = Cast<AAI_MyProject16Character>(PawnInstigator);
 4     AMyAIController* EnemyController = Cast<AMyAIController>(GetController());
 5     
 6     if (Sense->CanHear(Location, Volume, false)) {
 7         if (EnemyController) {
 8             EnemyController->myBoard->SetValueAsObject("Target", PlayerPawn);
 9             EnemyController->myBoard->SetValueAsBool("isSeen", true);
10             //GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, "Hear the pawn and UpdateBlackboard!");
11         }
12     }
13 
14 }

 

 

与看见相同。

参数需要三个,且在if语句中通过Sense调用CanHear方法来判断他AI是否听到了玩家。

 

最后再增加一个装饰器,起名isChasing。

 

 

 

 1 // Fill out your copyright notice in the Description page of Project Settings.
 2 
 3 #pragma once
 4 
 5 #include "CoreMinimal.h"
 6 #include "BehaviorTree/BTDecorator.h"
 7 #include "AI_MyProject16Character.h"
 8 #include "isChasing.generated.h"
 9 
10 /**
11  * 
12  */
13 UCLASS()
14 class AI_MYPROJECT16_API UisChasing : public UBTDecorator
15 {
16     GENERATED_BODY()
17 
18 public:
19     UisChasing();
20 
21     virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const;
22 
23     UPROPERTY(VisibleAnywhere,BlueprintReadOnly)
24     float dist;
25 };

 

希望玩家与AI之间距离大与dist的时候,原地停止5秒钟。CalculateRawConditionValue是继承自父类的方法。

 

1 // Fill out your copyright notice in the Description page of Project Settings.
 2 
 3 
 4 #include "isChasing.h"
 5 #include "MyAIController.h"
 6 #include "Enemy.h"
 7 #include "Engine.h"
 8 
 9 UisChasing::UisChasing() {
10     bCreateNodeInstance = true;
11     dist = 100;
12 }
13 
14 bool UisChasing::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const{
15     
16 
17     AAI_MyProject16Character* PlayerPawn = Cast<AAI_MyProject16Character>(GetWorld()->GetFirstPlayerController()->GetPawn());
18     FVector targetLocation = PlayerPawn->GetActorLocation();
19 
20     AMyAIController* enemyController = Cast<AMyAIController>(OwnerComp.GetAIOwner());
21 
22 
23     AEnemy* enemyPawn = Cast<AEnemy>(enemyController->GetPawn());
24 
25 
26     FVector SelfLocation = enemyPawn->GetActorLocation();
27 
28     if (PlayerPawn && enemyPawn) {
29         float dists = (targetLocation - SelfLocation).Size();
30     
31         if (dists <= dist) {
32             GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Yellow, "Check!");
33             return false;
34         }
35         else
36         {
37             GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Yellow, "UnCheck!");
38             return true;
39         }
40     }
41     else {
42         return false;
43     }
44 }

 

装饰器只表示逻辑是否满足。
所以有返回值。


 

 

编译运行即可,本节不展示结果。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值