Unity3D人工智能编程精粹(txt+pdf+epub+mobi电子书下载)


发布时间:2020-06-30 12:43:49

点击下载

作者:王洪源,陈慕羿,华宇宁,石征锦

出版社:清华大学出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Unity3D人工智能编程精粹

Unity3D人工智能编程精粹试读:

前言

写作目的

Unity3D是近几年非常流行的一个3D游戏开发引擎,已成为手机游戏开发的主要开发工具之一,也用于计算机虚拟现实领域的模拟飞行、模拟射击、模拟驾驶等技术的开发。手机(或其他平台)的游戏逐渐高档化、复杂化,游戏角色也需要具有更高的“智能”。

游戏中角色的AI(人工智能)水平直接决定着游戏的惊险性、刺激性、趣味性,优秀的游戏会使人玩不释手。在人机对战的TPS(第三人称视角射击游戏)游戏中,为了让游戏可以被玩家接受,使游戏变得更加有趣,很大程度上要依赖于AI。可以想象,如果敌人角色都只会呆滞地、向前径直冲进玩家的炮火中,玩家很快就会对此失去兴趣而弃之。游戏《半条命》因老练狡猾的敌人“海军陆战队”的AI系统而闻名;《星际争霸》游戏因广泛使用了寻路技术而使我们看到了战场上士兵的编队移动,现已成为RTS(即时战略游戏)游戏的潮流。

现在国内出版的Unity3D书籍多为入门级的初级水平读物,尚无Unity3D游戏人工智能的专门中文书籍,而其专题内容一般只在互联网“论坛”上出现,却又缺少系统化详解。

为此,本书精选了游戏AI中最必要、最实用的几项关键技术,用大量Unity3D示例代码、图片,以深入浅出的方式讲解游戏人工智能理论、设计原则和Unity3D编程实现方法。每个程序都有详细的注释并运行测试通过。程序对Unity3D的版本(3.X/4.X/5.X)依赖性不大。希望本书能给具备初步Unity3D游戏开发编程能力的读者在创作“更高智能”游戏角色时提供系统地、快捷地帮助。主要内容

1. 第1章 Unity3D人工智能架构模型

对于游戏中的AI,应该关注的问题是如何让电脑能像人或动物那样“感知、决策、移动”,使游戏中的角色看上去像真实的人或动物。为了用Unity3D实现这一目标,使用AI的架构模型来分层次处理运动层、决策层、战略层的内容,并以此解析了FPS/TPS(第一、三人称射击游戏)中各层次的任务分解。

2. 第2章 实现AI角色的自主移动——操控行为

操控行为是指操作控制角色,让它们能以模拟现实的方式在游戏世界中移动。它的工作方式是通过产生一定大小和方向的操控力,使角色以某种方式运动。操控行为包括一组基本“行为”:使单独的AI角色靠近或离开目标、在角色接近目标时减速、使捕猎者追逐猎物、使猎物逃离捕猎者、使角色在游戏世界中随机徘徊、使角色沿着某条预定路径移动、使角色避开障碍物等行为。

操控组成小队或群体的多个AI角色(如模拟群鸟飞行)时,需要令其与其他邻居保持一定的距离、一致的朝向以及靠近其他邻居等行为。

操控行为优点是:使AI角色看上去很真实;非常易于计算,算法速度快。使用Unity3D提供的开源库UnitySteer可以快捷实现操控行为。

3. 第3章 找最短路径并避开障碍物——A*寻路

著名的A*寻路算法在游戏中有着十分广泛的应用,它可以保证在起点和终点之间找到最佳路径,在同类算法中效率很高,对于多数路径寻找问题它是最佳选择。本章给出了利用操控行为和A*寻路实现RTS中的小队寻路示例。

然而在实际游戏中,很多时候最短路径并不是最好的选择。在人类或坦克等在面对山地、森林等不同通过难度的地形时,在射击类游戏需要选择不易受敌人攻击的路线时,就需要采用战术寻路。本章给出了利用A* Pathfinding Project插件进行战术寻路的示例。

4. 第4章 AI角色对游戏世界的感知

当控制游戏角色的移动时,角色需要感知周围游戏世界的内部信息和外部信息。内部信息包括AI角色自身的生命值、武器、目标和运动状态等,外部信息包括敌人的位置、救生包位置、战友的位置及生命值、爆炸声的来源等。

可以采用轮询和事件驱动的方式对这些环境信息进行感知,引起相应的触发器动作,使AI角色做出相应的反应或行动。本章给出AI士兵的综合感知系统示例。

5. 第5~6章 角色自主决策——有限状态机及行为树

决策系统会对从游戏世界中收集到的各种信息进行处理(包括内部信息,外部信息),从而确定AI角色下一步将要执行的行为。(1)如果游戏的决策系统不是很复杂,只要利用FSM(有限状态机)就可以实现。第5章分别给出了用Switch语句实现的FSM和用FSM框架实现的通用的FSM示例。(2)在处理较大规模的问题时,FSM很难复用、维护和调试。为了让AI角色的行为能够满足游戏的要求,就需要增加很多状态,并手工转换大量的编码,非常容易出现错误。行为树(Behavior Tree)层次清晰,易于模块化,并且可以利用通用的编辑器简化编程,简洁高效。它为我们提供了丰富的流程控制方法,只要定义好一些条件和动作,策划人员就可以通过简单地拖曳和设置,来实现复杂的游戏AI。

作者在总结教学经验中体会到,初学者对行为树的设计思路理解较为困难,甚至互联网论坛上也常常看到因为对行为控制流程理解错误,导致很大程度上影响了对于行为树的正确应用。本章用较大篇幅详解了一个行为树的示例,一步步详细分析了它的执行流程,以期使读者能够准确掌握行为树并设计出具有更高“智能”的AI角色。

6. 第7章 AI综合案例——第三人称射击游戏

在本章中给出一个具有较高AI水平的第三人称射击游戏示例。其中主要用到了第3章的A*寻路、第6章的行为树等技术,使“敌人士兵”具有了较高的智能水平,它们可以自主寻找并移动到隐蔽点、躲藏在工事后面、下蹲以减少被玩家击中的概率、举枪瞄准玩家、对玩家射击……这些战术动作大大增加了游戏的惊险性、趣味性和挑战性!适用读者(1)对于具有初级开发水平的Unity3D游戏开发爱好者来说,这是一本非常好的AI入门读物。本书精选了游戏AI中最重要、最实用的几项关键技术,始终围绕着AI的技术精髓展开,同时用简单清晰的方式去实现它,读者可以在自己的计算机上运行示例代码,模仿书中提供的代码去快速实现一个“更高智能”的“敌人士兵”或其他AI角色。(2)对于游戏开发培训学校的师生来说,本书可作为Unity3D游戏开发的高阶教材。本书深入浅出,用实例讲解理论性较强的人工智能理论、设计原则以及实现方法。书中配有大量的插图,重视AI技术论述的条理性,便于组织教学。(3)本书可作为数字媒体技术、数字媒体艺术等专业的《游戏人工智能》课程教材,计算机科学与技术、自动化专业本科生、研究生的《人工智能》课程教材与实验参考书。由于一般院校都把《人工智能》作为专业选修课程,而且所使用的教材大多理论推导多、教材内容枯燥,如果以本书组织教学,将会大大提高学生的学习兴趣,同时会提高学生的实际编程水平。(4)对于计算机、虚拟现实技术等相关学科的科研人员而言,本书也很有益处。

游戏人工智能程序必须在有限的计算机硬件资源(CPU速度、内存大小、显卡性能)下工作,本书的“操控行为”、“A*寻路”、“有限状态机”、“行为树”等算法的实时性、高效性有待于更深一步地研究提高。

本书由沈阳理工大学信息科学与工程学院王洪源、陈慕羿、华宇宁、石征锦老师共同著作完成,另外,参与本书编写工作的还有张骥超、王清鹏、李鑫洋、杨竹、陈鹏艳等硕士研究生。在本书写作过程中得到了清华大学出版社计算机与信息分社杨如林编辑的大力帮助,在此表示感谢。第1章 Unity3D人工智能架构模型

Unity3D是近几年非常流行的一个3D游戏开发引擎,已经成为手机游戏主要的开发工具之一。该引擎也可以用于计算机虚拟现实领域的开发工作,比如模拟飞行、模拟射击、模拟驾驶等。手机(或其他平台)中的游戏逐渐高档化、复杂化,游戏角色需要具有更高的“智能”,特别是在大型三维网络游戏中,AI(人工智能)的开发占有重要的比例。游戏中角色的AI水平直接决定着游戏的惊险性、刺激性、趣味性,优秀的游戏会使人玩不释手。

本书的核心是采用Unity3D游戏引擎,使用C#脚本编程来实现这类智能任务。

人工智能(Artificial Intelligence,简称AI),是指由人工制造出来的系统所表现出来的模拟人类的智能活动,通常也指通过计算机实现的这类智能。在游戏中,对于AI,应该关注的问题是如何让游戏角色能像人或动物那样“感知”、“思考”和”行动”,让游戏中的角色看上去像具有真实的人或动物的反应。

本书用“AI角色”来表示游戏中由计算机控制,具有一定智能的非玩家角色。

事实上,对于游戏中的AI角色,可以认为它们一直处于感知(Sense)→思考(Think)→行动(Act)的循环中。● 感知:是AI角色与游戏世界的接口,负责在游戏运行过程中不断

感知周围环境,读取游戏状态和数据,为思考和决策收集信息。

例如,是否有敌人接近等。● 思考:利用感知的结果选择行为,在多种可能性之间切换。例如,

战斗还是逃跑?躲到哪里?一般说来,这是决策系统的任务,有

时也可能简单地与感知合二为一。● 行动:发出命令、更新状态、寻路、播放声音动画,也包括生命

值减少等。这是运动系统、动画系统和物理系统的任务,而动画

和物理系统由游戏引擎提供支持。

多年以来,从街机游戏《PaC Man(吃豆人)》中的小魔鬼到《使命召唤:现代战争3》、《光晕》等,AI给无数的游戏角色赋予了鲜活的生命力。

1. 决策系统中的“有限状态机”技术《PaC Man》(见图1.1)游戏中的AI或许是很多玩家曾经见过的最早的AI角色,该游戏中的敌人角色能和玩家作对,在关卡中像玩家一样移动,给玩家留下了深刻的印象。《PaC Man》采用了非常简单的“有图1.1 《PaC Man》游戏截图限状态机”技术。在游戏中,每个小魔鬼都处于追逐PaC Man或当PaC Man长大后被小魔鬼追逐而逃跑的状态中。对于每个状态,小魔鬼在交叉点处都会采用半随机的方式选择移动路线。在追逐模式下,每个小魔鬼都有不同的概率追逐PaC Man;在逃跑模式下,它们或者选择以最快速度跑开,或者选择一个随机的方向移动。《PaC Man》之后很久一段时间,AI游戏的开发几乎是在原地踏步,直到1990年代中期,AI又开始成为游戏的热点,一些游戏的宣传中甚至特别提到了AI来做为卖点。

有限状态机技术是最早产生的AI技术,时至今日依然有着强大的生命力,是AI中应用最为广泛的技术之一。同时,行为树技术也得到了越来越广泛的应用。

2. 潜行类游戏中的感知技术

在现代游戏中,感知与触发技术的使用十分普遍,它们会为玩家带来更加逼真的游戏体验。尤其是在潜行类游戏中,感知系统是最为重要的部分之一。1997年的《Goldeneye 007(黄金眼007)》游戏中,尽管采用了只包含少量状态的角色,但是加入了一个AI感知系统,使游戏中的角色能够看到他们的同伴,如果同伴被杀死,他就会感知并调整自身行为。1998年的《Thief:The 图1.2 《Metal Gear Solid》游Dark Project》和《Metal Gear Solid(合戏截图金装备)》(见图1.2)游戏中,引入了更加强大的AI感知,大大提升了游戏体验。

3. 运动系统中的自主移动与编队移动技术——“操控行为”与“A*寻路”技术

1994年,一款经典的即时战略游戏《星际争霸》(见图1.3)横空出世,在很短的时间里盖过了C&C系列的风头,成为RTS(Real-Time Strategy Game,即时战略游戏)游戏的新潮流,并且这股潮流一卷就是十几年。在玩家非常熟悉的图1.3 《星际争霸》游戏截图《星际争霸》游戏中,广泛使用了寻路技术与战场上士兵的编队移动,而《星际争霸2》中采用了第2章将介绍的群体操控行为。

时至今日,群体操控行为依然是游戏中最广泛采用的群体模拟技术,而A*寻路则是应用最为广泛的寻路算法。1.1 游戏AI的架构模型

尽管每种游戏需要的AI技术都有所不同,但绝大多数现代游戏中对AI的需求都可以用三种基本能力来概括。● 运动:移动角色的能力;● 决策:做出决策的能力;● 战略:战略战术思考的能力。

根据上面的需求,我们采用的AI架构模型如图1.4所示。在这个模型中,将AI任务划分为三个层级,分别为运动层、决策层和战略层。运动与决策层包含的算法是针对单个角色的,战略层是针对小队乃至更大规模群体的。在这三个层次的周围,是与AI密切相关的其他部分:与游戏世界的接口、动画系统、物理仿真系统等。

需要注意的是,这只是一种基本的AI架构模型。实际中,根据游戏的种类和需求,可能会有所细化或增删。例如,棋类游戏就只包含战略层,因为这种游戏中的角色不需要自己做出决定,也不用考虑如何移动。而其他许多非棋类游戏中,就不包含战略层,如平台游戏中的角色,可能是纯反应型的,只需要每个角色自己做出简单的决定,并且依此图1.4 通用的AI架构模型行动,而不需要角色之间的分工协作。在另一些类型的游戏中,可能还需要对这三层中的某层进行进一步细分,以满足更多的需求等。1.1.1 运动层

导航和寻路是运动层AI的主要任务,它们决定了角色的移动路径。当然,具体的移动行为还需要动画层的配合才能完成。

例如在《Splinter Cell(细胞分裂)》游戏的某些关卡中,当卫兵看到玩家时,需要拉响警报,这就需要它们首先移动到最近的、固定在墙上的警铃,而这个警铃可能距离卫兵较远,卫兵需要避开许多障碍或穿过走廊才能到达,要实现这些就需要较为复杂的导航或寻路算法。

当然,有许多行为是直接由动画层处理的。例如,在《模拟人生》游戏中,如果一个角色正坐在桌子旁边,面前放着食物,这时如果角色做出需要执行吃东西的决定,那么只需要播放吃东西的动画就可以了,不再需要其他AI。

运动层包含的算法能够把上层做出的决策转化为运动。

如果上层做出吃东西的决策时,这个角色正在门的后面,那么就需要运动层的参与:首先使角色移动到椅子那里,然后才能播放相关的动画。

当一个AI角色的决策层做出攻击玩家的决策时,运动层会利用与移动相关的算法,使角色接近玩家的位置,来执行这个决策,然后才会播放攻击动画,以及处理角色或玩家的生命值等。1.1.2 决策层

决策层的任务是决定角色在下一时间步该做什么。

在最简单的情况下,角色可以采用很简单的准则来选择行为。例如,只要角色看不到玩家,就进行巡逻,反之就进行攻击。在复杂的情况下,角色就需要更多的准则来选择行为,比如《半条命2:消失的海岸线》中的敌人AI向我们展现了复杂的决策,它们会采用许多不同的策略接近玩家,将多个中间行为,例如投掷手榴弹,压制敌人火力等组合到一起,从而达到目标。

一般情况下,每个角色都有许多不同的行为可以选择,例如攻击、隐藏、探索、巡逻等,因此,每个时间步,决策系统都需要判断哪些行为是最适合的。当决策系统做出决策后,由运动层和动画系统来执行决策。

一些决策可能会需要运动层来执行。例如,如果需要近身攻击,那么角色必须首先靠近攻击目标。也有些决策无需运动层执行,只需要动画系统的支持,或是只要更新游戏状态就可以了。

决策层的功能可以利用本书所介绍的有限状态机或行为树技术实现,也可以采用更加复杂的AI技术,如模糊状态机、神经网络等技术实现。1.1.3 战略层

即使游戏中只有运动层和决策层,也可以实现很复杂的功能。事实上,大部分基于行为的三维游戏只用到了这两个层次,但是,如果需要团队协作,那么还需要某些战略AI。

战略指的是一组角色的总体行为,这时AI算法并不是只控制单个角色,而是会影响到多个角色的行为。小组中的每个角色可以有它们自己的决策层和运动算法,但总体上,它们的决策层会受到团队战略的影响。

在较早的游戏《半条命2:消失的海岸线》中,敌人会进行团队协作,包围和消灭玩家。例如,一个敌人会冲过玩家,试图从侧翼进攻。更晚一些的游戏,例如《Tom Clancy's Ghost Recon》中,采用了更为复杂的团队战略行为,而现代的游戏用到的团队战略就更为复杂了。

战略层也可以利用本书所介绍的有限状态机或行为树技术实现,也可以采用更加复杂的AI技术,如模糊状态机、神经网络等技术实现。1.1.4 AI架构模型的其他部分

在实际中,要构造出好的AI角色,只有运动层、决策层和战略层是不够的,还需要许多其他相关技术的支持。例如,运动层需要向“动画系统”或“物理仿真系统”发出请求,以便将移动进一步转换为具体的行动。

AI还需要感知游戏世界的信息,找出角色能够获知的信息,来做出合理的决策,可以称之为“感知系统”。它不仅仅包含每个角色可以看到和听到的内容,还包括游戏世界与AI的所有接口。1.2 FPS/TPS游戏中的AI解析

FPS(First Person Shooter Game,第一人称视角射击游戏)就是以玩家的主观视角来进行射击的游戏;TPS(Third Person Shooting,第三人称视角射击游戏)是指玩家控制的游戏人物在游戏屏幕上是可见的,因而第三人称射击游戏更加强调动作感。

在过去的许多年中,FPS/TPS战斗AI的“进化”十分缓慢,大多数电脑控制的敌人角色都只会呆滞地向前径直冲进玩家的炮火中,直到Valve发布了《半条命》才改变了这种状况。为了让游戏可以被玩家接受,使游戏变得更加有趣,FPS游戏很大程度上依赖于战斗AI。在《半条命》中,战斗AI有了很大的提高,“海军陆战队”展示出了前所未有的AI级别,包括被击中时的不同反应、发现手榴弹,甚至对于玩家、伙伴和敌人具有真实感的认知。《半条命》因老练狡猾的敌人的AI系统而闻名。

FPS/TPS游戏中的AI通常用分层结构来实现。高层负责进行推理决策,选择适当的与策略匹配的行为;低层负责处理最基本的任务,确定到目标位置(这个目标位置由更高层决定)的最优路径,或是播放适当的动画序列。当AI系统确定了采取何种行为时,低层模块需要选择完成这项任务的最佳策略。低层模块接收到命令,使角色参加战斗,它会尝试确定当前最佳的方法——悄悄接近敌人,隐藏在角落中,等待机会或直接跑向敌人或疯狂地射击。1.2.1 FPS/TPS中的运动层

运动层的任务是确定角色如何在游戏世界中移动,负责让角色避开障碍物,沿着导航系统确定的节点移动,并且在复杂的环境中寻找到达目标点的路径。运动子系统不会决定移动到哪里,只决定怎么移动到指定地点。它接收来自其他部分的命令,告诉它去往哪里,然后确保角色以合适的方式移动到那里。

总的来说,这一层负责执行高层分配给它的任何任务。这些任务是采用移动命令发出的,例如,移动到点(X,Y,Z),移动到目标B,面向点(X,Y,Z)或者“停止移动”。

这一层涉及到的主要算法是寻路。在每个关卡中,寻路部分负责寻找从任一坐标点到另一个坐标点的路径。给定一个出发点、一个状态标识、一个目标或目的地,它会找到一系列航点,组成一条最优路径。当找不到路径可以到达目标点时,它会报告找不到路径。

另外,它也可以处理不同类型的移动,例如走路、跑、游泳等,并采用适当的参数来确定AI角色的加速度、运动范围、转动速率、动画以及其他的运动特性。1.2.2 FPS/TPS中的决策层

在射击游戏中,决策层确定了角色的当前目标、命令、状态和当前目的地,并与其他层通信,使角色协调地运动到一个指定的目标地点。

具体来说,这一层决定了AI的执行行为,如播放哪个动画、播放哪个音频文件、移动到哪里、何时以及如何投入战斗。根据游戏的不同需求,决策层可以有多种实现方式,大多数FPS游戏都采用有限状态机或行为树技术实现。

由于在多数射击游戏中,战斗是关键部分,因此在用户评估AI时,与战斗相关的决策是十分关键的。因此,可以在决策层中,除了一般的决策之外,再增加一个单独的“战斗控制器”,这个战斗控制器负责做出与战斗相关的决策,它可以利用有限状态机或行为树技术类实现。在一些实际游戏中,包含战斗控制器的决策层是利用层次状态机或行为树技术来实现的,例如微软的《光晕》系列游戏等。

对于一个典型的FPS游戏中的AI角色,下面列出了几个典型状态。● 空闲:角色没有参与战斗或移动。● 巡逻:角色沿着给定的巡逻路线进行巡逻。● 战斗:角色处于战斗中,这时大部分事情交给战斗控制器处理。● 徘徊:角色没有参与战斗或移动。● 逃跑:角色试图逃离敌人或某种感觉到的威胁。● 寻找:角色正在寻找可以战斗的敌人,或寻找在战斗中逃跑的敌

人。

当角色开始战斗时,大多数行为控制便交给了战斗控制器,它负责所有相关的任务,例如选择敌人、选择武器、操作武器、开火、选择额外的武器和弹药等。但最困难的部分是如何智能地对当前环境做出反应,并选择执行适当的策略,这里需要考虑的问题主要包括以下几个方面。

1. 策略选择

对于任何战斗场景,游戏决策层都需要选择最好的策略攻击敌人,让游戏更具有挑战性。这个决策依赖于三个主要因素:正在考查的策略特点、其他战士的相对策略、不同的位置以及当前的状况(角色的生命状况(包括武器、弹药和位置),加上同伴和对手的生命状况(包括武器、弹药等))。

2. 战斗部分的任务

评估角色的当前境遇、选择战斗策略、瞄准和向对方开枪、决定何时选择新的武器等。

3. 如何选择敌人

对于多个敌人,战斗AI需要挑选出一个敌人作为当前的目标,因为一个角色在某一时刻只能对付一个敌人。当AI选择好目标,并初始化战斗后,如果境遇发生变化,它需要考虑改变目标;如果目标死亡,便需要重新确定目标。

4. 目标选择

在复杂的游戏场景中,通常很容易找到一个好的目标选择策略,因为只需考虑角色与潜在敌人的关系就可以了。角色首先需要进行自身的防御,确定是否有对手在威胁他的安全。如果没有,他可以选择最近的、最脆弱的目标进行攻击。使用一个简单的排序函数就可以做出决定,并调用合适的战斗命令。

5. 武器射击点位置

大多数FPS武器是高速的射击武器,这时的核心问题是确定向哪里开火;相反,如果武器是低速的,便需要预测敌人在未来时刻的位置,并朝向这个未来位置进行射击。1.2.3 FPS/TPS中的战略层

在射击游戏中,需要的AI一般主要针对单独的个体角色,而不是相互协作、采用相同策略进行同步的小队。但是,如果你的游戏中,例如,游戏是基于分队战斗的,需要考虑分队成员之间的协作,那么可能会需要一个战略层。

战略层可以很简单,例如,只作出分队前进、撤退或掩护的决策,也可能很复杂,例如让分队中的某些成员进行攻击,其他成员继续前进或提供掩护,然后在前方某点会合等。1.2.4 FPS/TPS中AI架构模型的支撑部分

1. 感知部分

任何人只需看一眼周围环境,便立刻能够形成对空间的理解,而让一个AI角色去理解某个区域的空间配置却很困难。角色的感知可以划分为视觉子系统、听觉子系统和策略子系统。视觉子系统考虑距离、视场的角度以及当前的可视级别(例如光线、雾和障碍等)。为了确保角色确实能够看到物体,我们一般需要调用Raycast进行查询,另外,角色还要能够感知到受伤害、碰撞等。

2. 动画部分

动画部分负责控制角色的骨骼关节,它的主要任务是选择动画,选择动画参数,并且播放角色运动序列。动画系统按照选择的速度播放动画,也可以让身体的不同部分播放不同的动画。例如,一个士兵可以在奔跑的同时瞄准敌人,也可以在奔跑时射击和更换武器。这种类型的游戏一般采用反向动力学系统(IK)实现。高层模块的任务是选择与当前状况适合的行为,例如,是否寻路某个区域、进入战斗或走遍地图搜索敌人。第2章 实现AI角色的自主移动——操控行为

初学Unity3D时常常会遇到这样的情景:设计的游戏角色在行进过程中遇到障碍物而无法避开,它不停地与障碍物碰撞,与障碍物做相对滑动,一直到滑出障碍物为止;有时,它也可能会一直卡在那里,不停地原地踏步,这简直槽糕极了!

通过本章,读者可以学习到如何让AI角色实现自主移动。● 如果角色需要从A移动到B,但被路上的一堵墙挡住了去路,那

么它会做出相应地反应,调整自己的行为,而不是机械地贴在墙

上播放行走动画却丝毫无法前进。● 如果一个角色发现了比它强大得多的敌人正在靠近,那么应该立

即逃走,而这个更强大的敌人也会自行去追逐逃走的角色。在这

个逃走过程中,追逐者会预测逃跑者的未来位置,并前往预测的

方向拦截,而不是傻乎乎地一直跟在逃跑者的后面。● 在一个足球游戏中,玩家希望正在试图接球的球员会预测球的位

置,向预测的方向奔跑,或是在接近球的时候减慢速度准备接球,

而不是保持常速,在球到达时突然停住,或是控制不住速度而直

接从球旁边冲过去。● 对于一个需要巡逻的角色,玩家可能希望它能在场景中随机的徘

徊游荡,而不希望它沿着几个固定的巡逻点,来回地周期往复。● 如果一个角色需要穿越火力而前往某个目标点完成任务,玩家显

然会希望它能在途中尽量避开危险,安全到达目标点,而不是大

摇大摆地穿过火力线而过早被击毙。● 对于多个单位组成的小队,例如一群飞鸟、一个机组、一个虫族

的小队、一个鱼群、一个兽群,甚至人群,玩家不希望它们像仪

仗队那样机械地保持队形且路线完全一致地运动,而是希望它们

的运动既有一致性,但同时还呈现出某些个性,看上去更加真实

生动。1986年,Craig Reynolds提出了“集群”和“操控行为”的概念,用来仿真鸟的行为。他的论文发表在1987年的SIGGRAPH会议上,他还利用这种方法做了一个动画短片Stanley and Stella in:Breaking the Ice,片中呈现的内容十分精图2.1 鸟和鱼的集群行为,摘彩,其中最生动的是图2.1所示的鸟群的自动画短片Stanley and Stella in:Breaking 集群行为。the Ice从图2.1中可以看到,鸟群显示出某种一致性、聚合图2.2 电影《蝙蝠侠归来》中的 且部队性,但又并不是完全整齐排列地向一个方向飞翔或游动,而是呈现一定的随机性。鸟群的行为看上去很自然、逼真,因此产生了深远的影响。

1992年,在蒂姆波顿的电影《蝙蝠侠归来》(见图2.2)中,蝙蝠群和向高谭市进军的企鹅部队都是用这种技术生成的。从此以后,这项技术便被大量应用于电影和游戏中,电影《狮子王》、《指环王》中都应用了这项技术。在《指环王》中,通过使用Massive软件实现了操控行为。游戏中也经常应用这项技术,比如大家都很熟悉的游戏《半条命》和《星际争霸》。“操控行为”是指操作控制角色,让它们能以模拟真实的方式在游戏世界中移动。它的工作方式是通过产生一定大小和方向的操控力,使角色以某种方式运动。(1)操控行为包括一组基本“行为”。对于单独的AI角色,基本操控行为包括:● 使角色靠近或离开目标的“Seek ”、“Flee”行为;● 当角色接近目标时使它减速的“Arrival”行为;● 使捕猎者追逐猎物的“Pursuit”行为;● 使猎物逃离捕猎者的“Evade”行为;● 使角色在游戏世界中随机徘徊的“Wander”行为;● 使角色沿着某条预定路径移动的“Path Following”行为;● 使角色避开障碍物的“Obstacle Avoidance”行为等。

基本行为中的每一个行为,都产生相应的操控力,将这些操控力以一定的方式组合起来(实际上就相当于将这些基本“行为”进行了不同的组合),就能够得到更复杂的“行为”,从而实现更为高级的目标。(2)对于组成小队或群体的多个AI角色,包括基本的组行为如下。● 与其他相邻角色保持一定距离的“Separation”行为;● 与其他相邻角色保持一致朝向的“Alignment”行为;● 靠近其他相邻角色的“Cohesion”行为。

无论整个群体中有多少个个体,对于每个个体,计算的复杂性都是有限的,通过这种简单的计算,就可以产生逼真的效果。采用这项技术,两个相似的鸟群,即使是飞过相同的路线,它们的行为也是不同的。如果将这种真实性与其他采用中心控制机制的AI方法相比,就更容易看到它的特别之处。

这种方法的缺点在于,由于它无法预测,可能会出现无法预料的行为,也因此效果更真实、自然。为了得到更可靠的结果,在使用时许多参数需要通过实验调整,不过调整的过程中往往也会看到很有趣的结果。

为了使读者准确掌握本章内容以及阅读相关游戏人工智能英文书籍、资料提供方便,本书列出了以下中英文术语对照及释义,见表2.1所示。表2.1 操控行为术语中英文对照表2.1 Unity3D操控行为编程的主要基类

本节的内容位于AI模型中的运动层(见图1.4 :通用的AI构架模型),编程中主要涉及到Vehicle类、AILocomotion类和Steering类,它们是实现操控行为的基础。2.1.1 将AI角色抽象成一个质点——Vehicle类

首先对AI角色做出抽象。假设AI角色的基类名称为“Vehicle”,这个类名的直译为“交通工具”,但实际上它包括了很宽泛能自主移动的任何AI角色,如有轮机器、马匹、飞机、汽车、潜水艇、动物、人类和怪物等。

在AI构架模型中,操控AI角色的基类Vehicle把操作的对象抽象为一个质点,它包含位置(position)、质量(mass)、速度(velocity)等信息,而速度随着所施加力的变化而变化。由于速度意味着是实际物理实体,施加在其上的力和能达到的速度都是有限制的,因此还需要最大力(max_force)和最高速度(max_speed)两个信息。除此之外,还要包含一个朝向(orientation)的信息。

综上,这个“交通工具”位置的计算方法是这样的:(1)确定每一帧的当前操控力(最大不超过max_force);(2)除以交通工具的质量mass,可以确定一个加速度;(3)将这个加速度与原来的速度相加,得到新的速度(最大不超过max_speed);(4)根据速度和这一帧流逝的时间,计算出位置的变化;(5)与原来的位置相加,得到“交通工具”的新位置。

在这个简单的“交通工具”模型中,来自操控行为部分的控制信号只是一个向量——steering_force。当然,也可以采用更复杂的模型,这里不再做介绍。

在下面这个实现中,Vehicle是一个基类,其他所有可移动的游戏AI角色都由它派生而来。该实现封装了一些数据,用来描述被看作质点的“交通工具”,如车辆、马匹、飞机、潜水艇、动物、人类和怪物等。代码清单2-1 Vehicle.cs2.2.2 控制AI角色移动——AILocomotion类

AILocomotion类是Vehicle的派生类,它能真正控制AI角色的移动,包括计算每次移动的距离,播放动画等,下面是一个示例实现。代码清单2-2 AILocomotion.cs2.1.3 各种操控行为的基类——Steering类

Steering类是所有操控行为的基类,包含操控行为共有的变量和方法,操控AI角色的寻找、逃跑、追逐、躲避、徘徊、分离、队列、聚集等都可由此派生。这样,我们就可以在Unity3D中的C#脚本中方便地使用上述派生类来编程了。代码清单2-3 Steering.cs2.2 个体AI角色的操控行为

在开发一个飞船射击游戏、战略模拟游戏或第一人称射击游戏时,可能会遇到想让AI角色追逐或者避开玩家的情况。如在飞行模拟游戏中,让导弹跟踪和进攻玩家或玩家的飞行器。在这种情况下,可以运用本节介绍的技术。(1)有效地实现追逐或躲避等基本行为———让追猎者去追逐猎物,而猎物在不被抓到的情况下跑得越远越好;(2)当追猎者接近目标时,可能需要它减速,然后正好停止到目标位置,而不是高速冲过目标位置,然后再返回;(3)移动过程中还需要AI角色能够避开路上遇到的障碍物,这样AI角色就不会在追逐玩家的时候撞到障碍物上,并且被卡在那里,无法走出来;(4)有时可能需要AI角色在场景中徘徊,以便寻找敌人,或寻找补给等。在许多小游戏中,AI角色的徘徊行为都是围绕着几个事先指定的路点的,玩家一眼就能看出并预测它的行为,非常机械乏味。本节将介绍更加自然逼真的随机徘徊实现方法;(5)在某些时候,还需要AI角色能够沿着规划好的路径移动。2.2.1 靠近

操控行为中的靠近是指,指定一个目标位置,根据当前的运动速度向量,返回一个操控AI角色到达该目标位置的“操控力”,使AI角色自动向该位置移动。

要想让AI角色靠近目标,首先需要计算出AI角色在理想情况下到达目标的预期速度。该速度可以看作是从AI角色的当前位置到目标位置的向量。操控向量是预期速度与AI角色当前速度的差,该向量大小随着当前位置变化而变化,从而形成图2.3中该角色的寻找路径。图2.3 寻找与离开操控行为中的操控力计算

图2.3中的小三角表示AI角色,图中画出了它当前的运动速度、预期速度、计算出的操控向量以及实际的寻找路径。注意:由于操控行为是基于力和速度的,速度不会突变,因此,如果角色一直采取靠近行为,那么最终它将会从目标穿过,然后再返回重新接近目标,如此往复。这样产生的运动看上去就像飞蛾绕着灯飞舞。

当然,如果目标物体包含一个碰撞体,那么,接下来的行为就要由Character Controller决定了。如果不希望出现这种情况,可以采用后面介绍的抵达(Arrive)行为,也可以另外添加一些处理步骤。代码清单2-4 SteeringForSeek.cs

运行示例Example1_Seek.exe,(也可以自己建立场景,首先创建一个平面,设定一个目标点(例如图2.4中的小球)删除它的碰撞体,然后添加AI角色,图2.4 靠近行为演示并为它加上Character Controller组件、AILocomotion.cs脚本和SteeringForSeek.cs脚本),可以看到,AI角色正在接近目标。当它到达目标后,由于惯性的存在,会穿过目标、转向、再次接近目标。2.2.2 离开

离开和靠近行为正好相反,它产生一个操控AI角色离开目标的力,而不是靠近目标的力。它们之间唯一的区别是DesiredVelocity具有相反的方向。参见图2.3中的离开操控力和离开路径。

接着,还可以进一步调整,只有当AI角色进入目标周围一定范围内时,才产生离开的力,这样可以模拟出AI角色的有限感知范围。

这里采用了Vector3.Distance函数来计算当前位置与目标位置之间的距离。事实上,如果采用Vector3.sqrMagnitude函数,将会得到更快的计算速度,因为省去了计算平方根的时间,这时可以预先计算fearDistance的平方并存储到一个变量中。代码清单2-5 SteeringForFlee.cs

运行示例Example2_Flee.exe,如图2.5所示。可以看到当AI角色距离目标小于逃跑距离时,它会沿着与目标相反方向跑开。图2.5 离开行为演示2.2.3 抵达

有时我们希望AI角色能够减速并停到目标位置,避免冲过目标,例如,车辆在接近十字路口时逐渐减速,然后停在路口处,这时就需要用到抵达行为。

在角色距离目标较远时,抵达与靠近行为的状态是一样的,但是接近目标时,不再是全速向目标移动,而代之以使AI角色减速,直到最终恰好停在目标位置,如图2.6所示。何时开始减速是通过图2.6 抵达行为参数进行设置的,这个参数可以看成是停止半径。当角色在停止半径之外时,以最大速度移动;当角色进入停止半径之内时,逐渐减小预期速度,直到减小为0。这个参数的设置很关键,它决定了抵达行为的最终效果。代码清单2-6 SteeringForArrive.cs

运行示例Example3_Arrival.exe,如图2.7所示。可以看出,AI角色的确从进入减速区域后开始减速,并且稳稳地停在了目标点!图2.7 抵达行为演示2.2.4 追逐

追逐行为与靠近行为很相似,只不过目标不再是静止不动,而是另一个可移动的角色。最简单的追逃方式是直接向目标的当前位置靠近,不过这样看上去很不真实。举例来说,大家都知道,当动物追逐猎物的时候,绝不是直接向猎物的当前位置奔跑,而是预测猎物的未来位置,然后向着未来位置的方向追去,这样才能在最短时间内追上猎物。在AI中,把这种操控行为称为“追逐”。图2.8 追逐和逃避行为

图2.8中画出了被追逐的目标体,图中表明了它的当前位置和一段时间之后的预测位置,还画出了追逐者、它的当前速度和方向以及实际追逐路径。可以看出,追逐是朝向未来位置,而不是朝向当前位置的。

怎样实现这种智能的追逐行为呢?我们可以使用一个简单的预测器,在每一帧重新计算它的值。假设采用一个线性预测器,又假设在预测间隔T时间内角色不会转向,角色经过时间T之后的未来位置可以用当前速度乘以T来确定,然后把得到的值加到角色的当前位置上,就可以得到预测位置了。最后,再以预测位置作为目标,应用靠近行为就可以了。

实现追逐行为的一个关键是如何确定预测间隔T。可以把它设为一个常数,也可以当追逐者距离目标较远时设为较大的值,而接近目标时设为较小的值。

这里,设定预测时间和追逐者与逃避者之间的距离成正比,与二者的速度成反比。

一些情况下,追逐可能会提前结束。例如,如果逃避者在前面,几乎面对追逐者,那么追逐者应该直接向逃避者的当前位置移动。二者之间的关系可以通过计算逃避者朝向向量与AI角色朝向向量的点积得到,在下面代码中,逃避者朝向的反向和AI角色的朝向必须大约在20度范围之内,才可以被认为是面对着的。注意:背景知识:在二维空间中,向量a=(a1,a2)与向量b=(b1,b2)的点积(也称为“内积”)为:a·b=a1b1+a2b2=|a||b|cosθ。其中|a|表示向量a的长度,θ是两个向量之间的夹角。当两个向量都是单位向量时(即长度为1),那么它们之间的点积实际上就是这两个向量之间夹角的余弦;若两个非零向量的点积为负,那么两个向量之间的夹角大于90度;如果点积为0,那么两个向量相互垂直;如果点积为正,那么两个向量之间的夹角小于90度。代码清单2-7 SteeringForPursuit.cs

运行示例场景Example4_Pursuit,如图2.9所示。追逐者从A点出发,此时被追逐者正从B点向目标小球前进,经过一段时间后,追逐者走过的路线是从A到C,而被追逐者走过的路线是从B到D。可以看出,追逐者沿着预测的方向进行追逐。图2.9 追逐行为演示2.2.5 逃避

逃避行为是指使猎物躲避捕猎者。举例来说,鹿被狼追逐,鹿要不断变换逃跑方向,试图逃离狼预测的追逐方向。

逃避行为与追逐行为的不同是它试图使AI角色逃离预测位置。实现追逐行为的一个关键是如何确定预测间隔T,可以把它设为一个常数,也可以当AI角色距离目标较远时,设为较大的值,而接近目标时,设为较小的值。代码清单2-8 SteeringForEvade.cs

运行示例Example5_Evade.exe,如图2.10所示。这里追逐者从A点出发开始追逐,而被追逐者从B点出发。对于被追逐者B,首先激活靠近行为走向目标位置,5秒之后到达D点,此时关闭靠近行为,激活逃避行为,开始逃避追逐者。在这段时间内,追逐者走过的路线是从A到C,而被追逐者是从B到D(此时是靠近行为),然后从D到E(逃避行为)。图2.10 逃避行为演示2.2.6 随机徘徊

许多时候,人们需要让游戏中的角色在游戏环境中随机移动(如巡逻的士兵、惬意吃草的牛羊等),就像这些角色是在等待某些事情发生,或者是在寻找什么东西。当角色出现在玩家的视线范围内时,人们通常希望这种随机移动看上去是真实的,如果玩家发现角色实际上是在沿着预先定义好的路径移动,就会有不真实的感觉,那么便会影响到他的游戏体验。

随机徘徊操控行为就是让角色产生有真实感的随机移动。这会让玩家感觉到角色是有生命的,而且正在到处移动。

利用操控行为来实现随机徘徊有多种不同的方法,最简单的方式是利用前面所提到的靠近(Seek)行为。在游戏场景中随机地放置目标,让角色靠近目标,这样AI角色就会向目标移动,如果每隔一定时间(如几秒)就改变目标的位置,这样角色就永远靠近目标而又不能到达目标(即使到达,目标也会再次移动)。这个方法很简单,粗略地看上去也很不错,但是最终结果可能不尽如意。角色有时会突然掉头,因为目标移动到了它的后面。Craig Reynolds提出的随机徘徊操控行为解决了这个问题。(见参考文献[3])

解决问题的工作原理同内燃机的气缸曲轴传动相似,见图2.11所示。在角色(气缸)通过连杆联结到曲轴上,目标被限定曲轴圆周上,移向目标(利用靠近行为)。为了看得更似随机徘徊,每帧给目标附加一个随机的位移,这样,目标便会沿着圆周不停地移动。将目标限制在这个圆周上,是为了对角色进行限制,使之不至于突然改变路线。这样,如果角色现在是在向右移动,下一时刻它仍然是在向右移动,只不过与上一时刻相比,有了一个小的角度差。利用不同的连杆长度(Wander距离)、角色到圆心的距离(Wander半径)、每帧随机偏移的大小,就可以产生各种不同的随机运动,像巡逻的士兵、惬意吃草的牛羊等。图2.11 计算随机徘徊行为所需操控力的方法代码清单2-9 SteeringForPursuit.cs

运行示例场景Example6_BotsWander,如图2.12所示。其中有5个AI角色,它们都采用了徘徊行为,但具有不同的参数设置。如前所述,通过改变程序中的wanderRadius,wanderDistance和wanderJitter的值,会图2.12 随机徘徊行为实验中多得到不同特点的曲线:有的变化平缓,次得到的不同徘徊曲线有的会产生急剧的转弯。可以看出,不同的参数设置得到不同特点的徘徊曲线。2.2.7 路径跟随

就像赛车在赛道上需要导航一样,路径跟随会产生一个操控力,使AI角色沿着预先设置的轨迹,构成路径的一系列路点移动。

最简单的跟随路径方式是将当前路点设置为路点列表中的第1个路点,用靠近行为产生操控力来靠近这个路点,直到非常接近这个点;然后寻找下一个路点,设置为当前路点,再次接近它。重图2.13 路径跟随示意图复这样的过程直到到达路点列表中的最后一个路点,再根据需要决定是回到第1个路点,还是停止到这最后一个路点上,如图2.13所示。

这里假设路径是开放的,角色需要减速停止到最后一个路点上,因此需要用到抵达行为和路径跟随行为。

有时路径有起点和终点,有时路径是循环的,是一个永不结束的封闭路径。如果路径是封闭的,那么需要回到起点重新开始;如果是开放的,那么AI角色需要减速(利用抵达行为)停到最后一个路点上。

在实现路径跟随行为时,需要设置一个“路点半径(radius)”参数,即当AI角色距离当前路点多远时,可以认为它已经到达当前路点,从而继续向下一个路点前进。这个参数的设置会引起路径形状的变化,如图2.14所示。图2.14 路点半径的影响代码清单2-10 SteeringFollowPath.cs

场景设置及运行结果

步骤1:新建一个场景,创建一个平面作为地面,然后设置一些路点。这里为了清楚地显示出路点,通过创建小立方体来表示每个路点。把小立方体拖到合适的位置。注意要在每个小立方体的Inspector面板中删掉Box Collider,否则AI角色会和代表路点的小立方体发生碰撞。

步骤2:将带动画的AI角色模型拖到场景中,为它加上Character Controller,然后加上AILocomotion.cs脚本和SteeringFollowPath.cs脚本,如图2.15(a)所示。然后,为它创建一个Prefab,然后利用这个Prefab,在场景中添加多个AI角色。做好的游戏场景的Hierarchy面板如图2.15(b)所示。图2.15(a) AI角色的Inspector面板图2.15(b) 游戏场景的Hierarchy面板

参见图2.16,图中的小方块是设置的4个路点,黑色的线是AI角色走过的轨迹。

可以看出,采用如上操控方式进行路径跟随,产生的路径很自然,呈现出曲线而不是多段线段的样子,看上去更加真实。图2.16 AI角色实现路径跟随操控行为时的行走轨迹2.2.8 避开障碍

避开障碍行为是指操控AI角色避开路上的障碍物,例如在动物奔跑时避免与树、墙碰撞。当AI角色的行进路线上发现比较近的障碍时,产生一个“排斥力”,使AI角色远离这个障碍物;当前方发现多个障碍物时,只产生躲避最近的障碍物的操控力,如图2.17所示。这样,AI角色就会一个接一个地躲避这些障碍物。图2.17 躲避障碍物所需的操控力计算方法

在这个算法中,首先需要发现障碍物。每个AI角色唯一需要担心的障碍物就是挡在它行进路线前方的那些物体,其他远离的障碍物可以不必考虑。该算法的分析步骤如下。(1)速度向量代表了AI角色的行进方向,可以利用这个速度向量生成一个新的向量ahead,它的方向与速度向量一致,但长度有所不同。这个ahead向量代表了AI角色的视线范围,其计算方法为:

ahead=position+normalize(velocity)×MAX_SEE_AHEAD

ahead向量的长度(MAX_SEE_AHEAD)定义了AI角色能看到的距离。MAX_SEE_AHEAD的值越大,AI角色看到障碍的时间就越早,因此,它开始躲避障碍的时间也越早。图2.18 躲避障碍物所需的操控力计算方法(2)每个障碍物都要用一个几何形状来表示,这里采用包围球来标识场景中的每个障碍。

一种可能的方法是检测从AI角色向前延伸的ahead向量与障碍物的包围球是否相交。这种方法当然可以,但这里采用简化的方法,更容易理解,且能够达到相似的效果。

这里还需要一个向量ahead2,这个向量与ahead向量的唯一区别是:ahead2的长度是ahead的一半,如图2.18所示。计算方法如下。

ahead=position+normalize(velocity)×MAX_SEE_AHEAD×0.5(3)接下来进行一个碰撞检测,来测试这两个向量是否在障碍物的包围球内。方法很简单,只需要比较向量的终点与球心的距离d就可以了。如果距离小于或等于球的半径,那么就认为向量在包围球内,即AI角色将会和包围球发生碰撞,如图2.19(a)所示(图中省略了ahead2向量)。

如果ahead与ahead2中的任一向量在包围球内,那么就说明障碍物挡在前方。

如果有多个障碍挡住了路,那么选择最近的那个障碍(即“威胁最大”的那个)进行计算。图2.19 躲避障碍物所需的操控力计算及躲避路线(4)接下来,计算能够将AI角色推离障碍物的操控力。可以利用球心和ahead这两个向量计算,方法如下:

avoidance_force=ahead-obstacle_center

avoidance_force=normalize(avoidance_force)×MAX_AVOID_FORCE

这里,MAX_AVOID_FORCE用于决定操控力的大小,值越大,将AI角色推离障碍物的力就越大。

图2.19(b)中,虚线显示出了AI角色避开障碍后的新行进路线。

采用这种方法的缺点是,当AI角色接近障碍而操控力正使它远离的时候,即使AI角色正在旋转,也可能会检测到碰撞。一种改进方法是根据AI角色的当前速度调整ahead向量,计算方法如下。

dynamic_length=length(velocity)/MAX_VELOCITY

ahead=position+normalize(velocity)×dynamic_length

这时,dynamic_length变量的范围是0~1,当AI角色全速移动时,dynamic_length的值是1。代码清单2-11 SteeringForCollisionAvoidance.cs

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载