游戏AI是什么?
AI = Artifical Intelligence = 人工智能
但是一般的游戏AI与平时我们所认识的人工智能那些有所不同,
游戏AI往往很少应用到神经网络、深度学习等等现在流行的技术。
这是因为主流的游戏AI主要是程序员预先定义编写好可能发生的行为,
而不具有人工智能那种自我“学习”的特性。(当然也有少部分游戏的AI使用自我学习的算法,例如《黑与白》)
游戏AI主要职责是模拟出智能行为,并非学习。
可以说,
游戏AI的目标主要是模仿游戏世界里的事物行为,而不是模仿真实人类玩家:
街道上走动的人群,天空中乱飞的小鸟,来回巡逻的守卫,兵线上的小兵...
要是模仿真实人类玩家,更应该使用“学习性”的人工智能(也是我们熟悉的那个人工智能),通过神经网络,深度学习等流行技术实现。
例如:围棋AI阿法狗,DOTA2的OPENAI
介绍一些有趣的游戏AI
《黑与白》
《黑与白》是一款意识超前的游戏,玩家在游戏中扮演上帝的角色,组建城市、发展文明。其中的宠物就有很高的智能程度,拥有自行学习的机制。做了坏事可以被玩家惩罚,惩罚后会改变行为,如果放任自如则会加重坏行为。有趣的是,这款游戏的首席人工智能官就是Demis Hassabis,也就我们熟悉的阿尔法狗之父。
《求生之路》
作为一款FPS游戏,很难说《求生之路》里的怪物有多智能——它们本来就该是愚蠢而凶猛的。真正有技术含量的是它的“导演系统”,AI Director作为后台的核心,会根据玩家在游戏中的具体表现调控游戏的节奏。怪物出现的地点、数量,何处刷新道具等等,配合上根据形势动态变换的音乐,给了用户更真实的游戏体验。
各种角色扮演/沙盒游戏中的NPC
在一些自由度较高的游戏中,为了让玩家更好的融入这个世界,游戏会对NPC进行很多详细的设定。比如在《巫师》系列中,每个NPC都有自己的性格设定,包括会话数据库,让他们可以进行丰富的动作和对话。在GTA这种沙盒游戏中更是这样。
游戏AI基本设计
实际世界的智能:
一个正常的智能生物,得先感知到周围的事物,才能思考下一步该做什么,才能做出反应行为。
基于这个便自然而然分出以下三个模块:
- 感知模块
- AI 模块
- 行为模块
感知模块:
一般的游戏AI,首先需要得到感知模块的感知信息输入。
例如:
- 一个NPC的视野范围内看到了有一个丧尸。
- 一个丧尸听到了玩家的脚步声。
- 足球队队员之间的传达配合信息。
//例如 一个正常生物的感知模块
class BiologyPerception{
public:
//将所有感知进行一次检测,返还所有感知到的信息
PerceptionInformaiton getPercetionInformation(){
PerceptionInformaiton information;
information.add(m_viewPCT.getPercetionInformation());
information.add(m_listenPCT.getPercetionInformation());
//...
return information;
}
protected:
//视野感知
//实现:视锥范围检测
ViewPerception m_viewPCT;
//听力感知
//实现:圆形范围声音检测
ListenPerception m_listenPCT;
//其他感知
//...
};
AI模块:
分析输入的信息后,进行逻辑运算,输出接下来想要做的行为的信息。
例如:
- NPC检查了这个丧尸,判断到它是自己的敌人,所以NPC想逃跑。
- 丧尸检查了这个玩家,判断到它是自己的敌人,所以丧尸想扑过去攻击。
- 中锋检查了前锋的带球情况,判断到它想传球,所以中锋想要去对应的位置接球。
可以把AI模块想象成一个大脑(为了类比,可以把下面的“AI”字样看成“大脑”):
- AI “寄生”在一个生物模型上(该生物模型被称为寄主)。
- AI 的生命周期是跟随生物模型的生命周期的。
- AI 能够获取生物模型的感知信息,分析之,并控制生物模型行动。
class BiologyAI{
public:
//计算寄主感知信息,并根据信息让寄主执行相应的行为
void caculate(){
//获取感知信息
auto information = m_master->mPerception.getPercetionInformation();
//根据感知信息,让寄主执行行为
if(information...)m_master->moveTo(...);
if(information...)m_master->attack();
//....
}
protected:
Biology* m_master;//寄主
};
行为模块
根据AI模块的输出信息,行为模块只要按部就班的执行相应行为就行。
一般的游戏模型应该提供相应的行为接口。
//一个例子:生物类提供 移动和攻击 这两个接口
class Biology{
public:
//生物的各种行为接口
//...
void moveTo(cosnt Position& pos);
void attack();
protected:
//生物的各种变量
//....
Position m_health; //当前位置
int m_attack; //攻击力
BiologyPerception m_perception; //感知模块
};
小结
这样,一种基本的设计就浮现了:
- 每个生物模型含有自己的感知模块,提供行为接口。
- 每个AI模型"寄生"于一个生物模型,根据该生物模型的感知模块,来让生物模型执行其行为。
AI模块:使用状态机?还是行为树?
游戏AI的核心代码,毋庸置疑就是AI模块部分。
在上面的例子,AI模块只是简单的if判断条件。
而实际上,很多游戏的AI是非常复杂,一堆if判断的设计是不可行的(可维护性极差且不宜扩展)。
早期游戏AI利用<状态机>这个设计模式来很好解决了这个AI设计问题。
可后来随着游戏的进步,现代游戏AI的复杂性连<状态机>设计都不能满足,于是便有了更具可维护性的<行为树>设计。
为了节省篇幅,本文不对<状态机>进行过多解释,感兴趣可到下面这个链接。
而在下一篇博文将介绍行为树在游戏AI中的应用。