UE4中的人工智能解析—ShooterGame替例

发表于2016-02-25
评论1 1k浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏程序行业精英群

711501594
UE4中的人工智能解析—ShooterGame为例
在UE4编辑器中,打开内容浏览器,右击鼠标,创建传说中的行为树:
之后便会得到存在一个根节点的空的行为树:

右侧是设置行为树的黑板资源,此资源可自己创建与定义。实质就是不同bot之间协调时使用的一些公共内存罢了,UE4只是简单实现,就是一些映射罢了。当然不用也可以哦,亲!

设置一颗如下行为树,和官网shootergame一样:

之后为了让此行为树跑起来,我们需要把他与我们的bot关联,在我们定义的bot中

在编辑器中赋值:

虽说这个行为树定义在这里,但是我们经常会在其controller中调用(来自ShooterAIController类中的代码):

AShooterAIController::AShooterAIController(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)

{

  BlackboardComp = PCIP.CreateDefaultSubobject(this, TEXT("BlackBoardComp"));//创建黑板组件

  BehaviorComp = PCIP.CreateDefaultSubobject(this, TEXT("BehaviorComp"));//创建行为树组件

bWantsPlayerState = true;

}

//此方法在控制类(controller)关联肉身(APawn,UE4为人物增添了角色类,当然也是APawn的子类)时调用,熟悉UDK脚本的应该知道。

void AShooterAIController::Possess(APawn* InPawn)

{

Super::Possess(InPawn);

AShooterBot* Bot = Cast(InPawn);

// start behavior

if (Bot && Bot->BotBehavior)//因为在编辑器中已经赋值,所以这里行为树指针的值非空

{

BlackboardComp->InitializeBlackboard(Bot->BotBehavior->BlackboardAsset);//利用黑板资源初始化黑板组件

                //获取黑板中的键ID

EnemyKeyID = BlackboardComp->GetKeyID("Enemy");

NeedAmmoKeyID = BlackboardComp->GetKeyID("NeedAmmo");

                //启动行为树

BehaviorComp->StartTree(Bot->BotBehavior);

}

}

可以看出这里便使得AIController与我们创建的黑板资源与行为树资源相关联。

最后我们看看,上面行为树中的服务是啥回事?先看UE4中:

这三个关键类UBTService_BlackboardBase,UBTServe_BlueprintBase,UBTService_DefaultFoces便是UE4为我们创建的基本的服务类,在shooterGame项目里,是继承的中间UBTServe_BlueprintBase类,显然是为了在蓝图中可视化。

注意其中的FindClosestEnemy函数,这是哪里来的??,请看AShooterAIController类中:

UFUNCTION(BlueprintCallable, Category=Behavior)//不用说这种声明是啥意思,看上图

void FindClosestEnemy();

void AShooterAIController::FindClosestEnemy()

{

APawn* MyBot = GetPawn();

if (MyBot == NULL)

{

return;

}

const FVector MyLoc = MyBot->GetActorLocation();

float BestDistSq = MAX_FLT;

AShooterCharacter* BestPawn = NULL;

for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)

{

AShooterCharacter* TestPawn = Cast(*It);

if (TestPawn && TestPawn->IsAlive() && TestPawn->IsEnemyFor(this))

{

const float DistSq = (TestPawn->GetActorLocation() - MyLoc).SizeSquared();

if (DistSq < BestDistSq)

{

BestDistSq = DistSq;

BestPawn = TestPawn;

}

}

}

if (BestPawn)

{

SetEnemy(BestPawn);

}

}

类似的有ShootEnemy:

UFUNCTION(BlueprintCallable, Category=Behavior)

void ShootEnemy();

void AShooterAIController::ShootEnemy()

{

AShooterBot* MyBot = Cast(GetPawn());

AShooterWeapon* MyWeapon = MyBot ? MyBot->GetWeapon() : NULL;

if (MyWeapon == NULL)

{

return;

}

bool bCanShoot = false;

AShooterCharacter* Enemy = GetEnemy();

if (Enemy && Enemy->IsAlive() && MyWeapon->GetCurrentAmmo() > 0)

{

if (LineOfSightTo(Enemy, MyBot->GetActorLocation()))

{

bCanShoot = true;

}

}

if (bCanShoot)

{

MyBot->StartWeaponFire();

}

else

{

MyBot->StopWeaponFire();

}

}


  加入GAD的核心用户QQ群:484290331,各类活动奖励任你拿,最新资讯任你读,众多教学任你免费学,如此好地方赶紧加入吧!另VR专属群:476511561,专业VR技术分享,专业导师指导为你答疑解惑,大型小型活动奖励等你拿,免费学习赚奖励的天地,欢迎你加入哟!


原文链接

著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

游戏学院公众号二维码
腾讯游戏学院
微信公众号

提供更专业的游戏知识学习平台