从零点五开始用Unity做半个2D战棋小游戏(九)
好久不见。
这是第26篇与游戏开发有关的文章。
| 写在最前
这次想要做一个简单且传统的战棋小游戏,大概的玩法是:在2D世界里创建一张由六边形地块组成的战斗地图,敌我双方在地图上轮流行动,并向对方发动攻击,先消灭掉所有敌人的一方将获得胜利。
预计将分为以下几篇(未完成前可能会调整...):
1、创建战场(已完成)
根据预定尺寸生成战场地图,并随机一些障碍物。
2、添加地图功能 (已完成)
实现战场格子点击反馈,地图导航及范围选定。
3、添加对战双方(已完成)
向战场中添加作战单位,作战单位轮流行动,可进行移动、攻击。
4、加入玩家控制(已完成)
玩家可控制一个战斗单位,手动选择移动目标及攻击单位。
5、添加常用的界面(已完成)
建立界面管理器,加入一些常用的界面。
6、添加常用的战场显示(已完成)
为战斗单位添加血条,加入伤害文字特效。
7、扩展作战单位(已完成)
丰富战斗元素,加入并实现手动释放不同类型的技能。
8、加入AI系统(上)(已完成)
建立超级简单的AI系统。
9、加入AI系统(中)
调整AI系统的决策方式。
10、加入AI系统(下)
总结AI系统。
11、扩展战场地图
丰富战场地图,加入地形及道具等元素。
12、规范战斗配置
可以通过规范化的数据结构配置战场、职业、技能、道具等。
本次的主题是:调整AI系统的决策方式。
项目使用的Unity版本为:Unity2018.3.0f2。
代码会上传至我的Github:https://github.com/elsong823/HalfSLG 中,有兴趣的同学请自取。
| 目标
上一篇所实现的AI系统,并不能带来什么特别的体验。因为每个AI的行为逻辑都是相同的。换句话说,这些被AI控制的战斗单位,没有自己的“个性”。
本篇将会对AI系统进行调整,重构AI决策逻辑,尝试使用数值配置来驱动AI的行为,以期使战斗变得更加有趣。
另外,本篇将会有大量的数据表、图,可能有些枯燥,希望您能耐心看下去,谢谢。
那就让我们开始吧。
| 思考的出发点
我是这么开始的。
首先,我对战场内出现的战斗单位,进行了角色(职业)划分,它们分别是:
1、坦克;
2、输出;
3、治疗。
好吧, 我猜你一定知道,这是最简单的铁三角组合,这里就不解释这三种角色的战场定位了。
刘关张应该也算是一种铁三角组合吧 (图源网络)
之所以做这样的设定,是为了可以从简单入手,对AI的行为进行分类。
| 行为分类
现在,结合上述三种定位,试想一下我们自己在扮演这三种角色做决策时的样子。
我们可以近似的将AI的行为分为以下几类:
1、制造仇恨(嘲讽);
2、制造伤害(输出);
3、恢复队友(恢复)。
其实,上述三种行为,都可以理解为是主动采取的行为,也可以认为是一种理性的战斗策略。
但是,生活中的决策都是理性的么?
显然不是。
否则就不会有双十一、双十二什么事儿了。
某喵节 (图源网络)
| 愤怒机制
冲动是魔鬼,但冲动也会让角色更有血肉。
所以,我添加了一个愤怒机制,来模拟这种情绪上的冲动。
试想一下你被招惹急了会做什么?气哭了?确实,有时候会这样。但是更多的时候,你会想把对方胖揍一顿来渲泄这种愤怒。
因此,愤怒机制在系统中起到的作用就是强化伤害输出的决策。
愤怒与策略行为的关系
那么愤怒如何被积累呢?这里使用的设定是:当一个单位受到攻击后,会增加愤怒值;同时,单位每回合行动后,会降低一些愤怒值。
| 差异性角色
综上所述,当我们在创造AI时,可以通过调整上述三者策略的比例,来塑造出有差异性的角色。
比如:一个制造仇恨策略比例较高的坦克,和一个造成伤害策略比例较高的坦克,它们在一场战斗中的表现可能是:前者更愿意保护队友,而后者则更喜欢追着对方揍。
那么哪种更好呢?
我觉得都很好,这就好比生物多样性,如果地球上只有人类,那我们的生活该多么的枯燥乏味,甚至无法生存。
所以我们要保护生态环境,爱护我们共同的家园。
世界自然基金会 (图源网络)
| AI系统的设计
其实,这个AI系统的设计非常的简单,我们拆开来看。
◇ 战斗行为系统(BattleBehaviourSystem)
每一个参与战斗的单位,都有一个战斗行为系统。
战斗单位通过这个行为系统,来决定下一步的行动,比如朝哪移动、向谁发动攻击、或者恢复谁的生命值等。
但是战斗行为系统本身并没有什么计算能力,它只是组织了一个信息环境,真正处理信息、产生具有参考意义信息的家伙,是系统装配的战斗行为计算芯片。
◇ 战斗行为计算芯片(BattleBehaviourChip)
如果你看过《机器猫》,也许还记得在有一集里他拿出了一个“能力磁带”,只要把这个磁带插到身体里,你就会掌握一种能力,比如秒变棒球手、摔跤手、哲学家等等。
陪伴成长的蓝胖子 (图源网络)
战斗行为计算芯片跟这个很像,如果一个行为系统装配了某种芯片;那么当这个单位需要决策下一步行动时,芯片就会结合系统所提供的信息环境,为其列出所有可行的行为,并且为它们打分。
当然,一个行为系统可能同时装配多种不同种类的芯片。
◇ 行为对象(BehaviourItem)
行为对象就是芯片计算出的行为信息的载体,它记录了这个行为针对的具体目标,以及行为的类型(伤害、嘲讽、治疗)等。
◇ 行为调节器(Adjustor)
有时候我们需要微调行为对象中的得分。比如,我们得到了伤害芯片为我们计算出每个目标的得分,但是在做决策前,某个行为调节器忽然想提醒我们应该优先照顾下对方的治疗,那么它就会适当调高对这个治疗的行为对象的得分,同时调低对其他角色的行为对象的得分。
当所有调节器工作完毕后,系统将会根据这些待决定的行为对象,制定决策对象。
◇ 决策对象(DecisionItem)
制定决策是一个计算具体方案的过程,比如移动到哪个格子,是待命还是使用哪个技能;而决策对象记录了这些计算的结果,战斗单位最终根据这个结果,来完成一次行动。
我们可以通过下图更直观的了解行为系统的工作流程。
行为系统工作流
以上就是战斗行为系统的简单介绍,那接下来我们思考一个问题:如何验证系统的有效性;或者,当我们调整了用于驱动行为的数值,如何直观的看到反馈。
| 对结果进行分析
事实上,我们可以在每次调整完数值后,安排一些AI加入战场进行实际作战。
通过观察他们在战斗中的表现;以及,分析每个单位在决策时输出的Log,可以在一定程度上达到检验系统有效性的目的。
一个战斗单位行动前各行为的得分
但是,这并不是一个好的方法。因为调整数值只是修改了产生决策的范围;而AI在决策上的变化,是很难在一两次的战斗中,通过观察过程捕捉到的。
下面,我们就尝试通过对战斗结果进行数据分析,捕捉数值调整后的反馈信息,来验证系统的有效性。
首先介绍一下测试环境,创建两只配置完全相同的队伍(Team_1和Team_2)。每队分别配备一名坦克,一名治疗及一名输出。
两只队伍的角色配置以及角色关键数值
角色所装配的技能
为了尽量抵消行动次序及出生位置可能对结果带来的影响,我们采用每场交换优先行动权,以及全员、全地图随机初始位置的方式,进行500场自动战斗。
自动战斗的逻辑我们之前已经完成了,所以这个过程是很快的。
500场自动战斗计算
500场自动战斗后,双方的获胜情况
可以看出,在同样的队伍配置下,双方的胜率是很接近的。
接下来,我们调整一些AI的参数,尝试模拟一些特殊类型(个性)的战斗角色,看看战斗系统会给我们带来怎样的反馈。
◇ 靠谱的坦克
增加Team_1坦克的嘲讽策略比例,再次对战500场后,与调整前的战斗结果进行对比。
提高了嘲讽芯片的决策系数占比
Team_1坦克使用技能的对比
输出伤害及承受伤害的对比
双方获胜情况对比
Team_1角色场均死亡次数对比
可以看出:
坦克使用伤害技能的频次降低,使用仇恨技能的频次增加,输出绝对值及输出占比减小。
但这提高了队伍的整体胜率。
原因可推测为,坦克更好的保护了输出及治疗,减少了他们受到攻击的机会及死亡次数,增加了他们输出伤害和治疗的时间,进而影响了整体胜率。
◇ 终结者
为Team_1的近战Dps的伤害芯片增加杀手调节器,使其成为“终结者”,他(她)会优先考虑攻击濒死目标。再次对战500场后,与调整前的战斗结果进行对比。
输出伤害的对比
场均击杀数量的对比
双方获胜情况对比
可以看出:
由于属性和所使用的技能都没有变化,所以终结者的输出伤害变动很小;但是他的击杀数量明显增加(抢人头)。
尽管队伍胜率增加了,但是队友都很讨厌他。
◇ 治疗压制
为Team_1的近战Dps所拥有的伤害芯片增加了职业权重调节器,并设置为治疗压制模式。从此,他莫名其妙的对敌方的治疗产生了难以言喻的奇妙情感,并一直重点照顾。
职业权重调节器的设置
Team_2接受治疗对比
Team_2 治疗承受伤害的来源及击杀来源的对比
双方获胜情况对比
可以看出:
治疗被对方输出特殊照顾,直接减少了她的治疗总量;而且由于自身不断遭受攻击,治疗把技能更多的用在了自己身上,无暇顾及其他队友,进而降低了整体胜率。
◇ 职业保镖
Team_2的坦克会优先保护己方治疗,只要看到她被揍,瞬间宠妻狂魔附体。
Team_2胜场存活率及剩余血量对比
双方获胜情况对比
Team_2接受治疗情况对比
可以看出:
Team_2的治疗得到更多保护,产生的治疗量增加,胜场存活率提升,提高了整体战斗力。
《保镖》海报 (图源网络)
后来在一次线下聚会时,坦克发现这个“治疗妹子”居然是个汉子...
◇ 职业杀手 vs 职业保镖
Team_1的近战Dps为治疗压制 + 终结者,Team_2的坦克为治疗职业保镖。
结果…
你猜。
《王牌保镖》海报 (图源网络)
| 写在最后
至此,调整AI系统的决策方式篇就介绍到这了。
如你所见,本篇所展示的例子,都是单因素实验;而且角色类型、技能、数值结构都非常简单。对比那些态度认真、具有复杂技能、数值等设计的游戏,可能不太具有说服力。
但本篇想要做的仅是对“用数值影响AI决策”的一种尝试,而且这种影响是可以在后期的数据分析中得到反馈的,从这点上讲,目的已经达到了。
下一篇将会对AI系统的设计做一个简单的总结。
最后,需要指出的是,前面提到的《机器猫》,后来已经改名为《哆啦A梦》了。
愿不忘初心。
下回见。
非常感谢您能读到这里,详细的代码可以移步Github(https://github.com/elsong823/HalfSLG)下载。
文章会在我的公众号 偶尔学学Unity 中不定期更新,欢迎关注,谢谢。