UE4 中的人工智能解析—ShooterGame为例
在UE4编辑器中,打开内容浏览器,右击鼠标,创建传说中的行为树:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQTM2MzA2MjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
之后便会得到存在一个根节点的空的行为树:
右側是设置行为树的黑板资源,此资源可自己创建与定义。实质就是不同bot之间协调时使用的一些公共内存罢了。UE4仅仅是简单实现。就是一些映射罢了。当然不用也能够哦。亲!
设置一颗例如以下行为树,和官网shootergame一样:
之后为了让此行为树跑起来。我们须要把他与我们的bot关联。在我们定义的bot中
在编辑器中赋值:
虽说这个行为树定义在这里,可是我们常常会在其controller中调用(来自ShooterAIController类中的代码):
AShooterAIController::AShooterAIController(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
BlackboardComp = PCIP.CreateDefaultSubobject<UBlackboardComponent>(this, TEXT("BlackBoardComp"));//创建黑板组件 BehaviorComp = PCIP.CreateDefaultSubobject<UBehaviorTreeComponent>(this, TEXT("BehaviorComp"));//创建行为树组件 bWantsPlayerState = true;
}
//此方法在控制类(controller)关联肉身(APawn。UE4为人物增添了角色类。当然也是APawn的子类)时调用。熟悉UDK脚本的应该知道。
void AShooterAIController::Possess(APawn* InPawn)
{
Super::Possess(InPawn); AShooterBot* Bot = Cast<AShooterBot>(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类中:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQTM2MzA2MjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
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<AShooterCharacter>(*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<AShooterBot>(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();
}
}
UE4 中的人工智能解析—ShooterGame为例的更多相关文章
- Java并发编程中的设计模式解析(二)一个单例的七种写法
Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...
- UE4中使用数据表(Data Table)
本文依据官方文档数据驱动游戏性元素整理而来. 做过游戏的应该都清楚,如果游戏稍微有点规模,那么使用数据驱动来做游戏一般是必不可少的一步,一般也就是策划通过本表的方式来解决.下面我们来简单说一下UE4中 ...
- .NET Core中的CSV解析库
感谢 本篇首先特别感谢从此启程兄的<.NetCore外国一些高质量博客分享>, 发现很多国外的.NET Core技术博客资源, 我会不定期从中选择一些有意思的文章翻译总结一下. .NET ...
- 【转载】 [unreal4入门系列之七] UE4中的Actor类和Pawn类
原文地址: http://www.52vr.com/article-558-1.html 现在我们开始进入UE4的代码开发工作.首先,UE4的类框架是非常庞大的,看起来有点让人措手不及.不过正因为UE ...
- maven中使用dom4j解析、生成XML的简易方法
此片文章主要写一些关于如何在maven工程中使用dom4j来解析或生成XML的建议方法,实际可使用的写法不仅限于如下所写的样例代码.此处进攻快速入手和提供思路使用. 首先配置pom.xml中的依赖的包 ...
- UE4 中的 C++ 编程介绍
https://docs.unrealengine.com/latest/CHN/Programming/Introduction/index.html UE4 中的 C++ 编程介绍 Unreal ...
- 「Python 编程」编码实现网络请求库中的 URL 解析器
摘要:怎么写出更短的代码并不是这次要讨论的话题.今天我们来研究一下:运行代码的计算机是如何找到目标服务器的? 相信各位 Python 开发者都用过 Requests 库,有些朋友还用过 WebSock ...
- UE4命令行参数解析
转自:https://blog.csdn.net/u012999985/article/details/53544389 一 .命令行参数简述命令行参数是一连串的关键字字符串,当运行可执行文件时可以通 ...
- 前进中的人工智能——聚焦Faculty Summit 2015人工智能主题研讨会
Summit 2015人工智能主题研讨会" title="前进中的人工智能--聚焦Faculty Summit 2015人工智能主题研讨会"> 在近几年上映的科幻大 ...
随机推荐
- [Oracle] Merge语句
Merge的语法例如以下: MERGE [hint] INTO [schema .] table [t_alias] USING [schema .] { table | view | subquer ...
- python多线程编程代码
参考了这篇文章,写的挺好的. http://blog.csdn.net/abcjennifer/article/details/49474897 import time import threadin ...
- JAVA学习之 异常处理机制
今天就来说说java的异常处理机制,异常处理不是第一接触,尤其是写过非常多c#的代码,基本都会写到异常处理的代码,事实上c#的异常处理与java的异常处理基本都是一样的,仅仅是在一些细节上不是非常一样 ...
- 使用Java语言实现,自己主动生成10个整数(1~100,求出生成数列中的最大值和最小值,不同意使用Arrays类的sort方法
这是考察主要的java基础,没啥难点,直接上代码,近期在准备面试,所以做一些基础的面试题练练手 public class Demo1 { public static void main(String[ ...
- PE文件结构(三) 输入表
PE文件结构(三) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 输入表 输入函数,表示被程序调用可是它的代码不在程序代码中的,而在dll中的函数.对于这些函数.磁盘上的可执行文 ...
- Mysqldump逻辑备份与恢复
文档结构: mysqldump备份影响性能,可能会把内存里面的热数据给冲刷掉,5.7后,新增一个参数,innodb_buffer_pool_dump_pct,控制每个innodb_buffer中转存活 ...
- autocomplete="off" 不起作用解决方案
autocomplete属性是表单字段中的HTML5新属性,该属性有两种状态值,分别为"on" 和 "off",该属性可省略:省略属性值后默认值为"o ...
- sql server Delete误操作后如何恢复数据
声明:本文是根据别人的经验https://blog.csdn.net/dba_huangzj/article/details/8491327写的总结 说明:update和delete时没有加where ...
- hiho 1620 - 股票价格3 - 无限制的单调队列?
题目链接 小Hi最近在关注股票,为了计算股票可能的盈利,他获取了一只股票最近N天的价格A1~AN. 小Hi想知道,对于第i天的股票价格Ai,几天之后股价会第一次超过Ai. 假设A=[69, 73, 6 ...
- hdu 2037 - 典型贪心*
题目链接 给一堆电视节目的起止时间,问最多能完整收看几个节目 --------------------------------------------------------------------- ...