从零点五开始用Unity做半个2D战棋小游戏(九)

发表于2019-04-04
评论5 1.04w浏览

好久不见。

 

这是第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、治疗。

 

好吧, 我猜你一定知道,这是最简单的铁三角组合,这里就不解释这三种角色的战场定位了。

7GEJD3J7tfL80E1sJnrq.png

刘关张应该也算是一种铁三角组合吧 (图源网络)

 

之所以做这样的设定,是为了可以从简单入手,对AI的行为进行分类。

 

| 行为分类

现在,结合上述三种定位,试想一下我们自己在扮演这三种角色做决策时的样子。

 

我们可以近似的将AI的行为分为以下几类:

1、制造仇恨(嘲讽);

2、制造伤害(输出);

3、恢复队友(恢复)。

 

其实,上述三种行为,都可以理解为是主动采取的行为,也可以认为是一种理性的战斗策略

 

但是,生活中的决策都是理性的么?

 

显然不是。

 

否则就不会有双十一、双十二什么事儿了。

 

08ioywCbabun2HkoadxK.png

某喵节 (图源网络)

 

| 愤怒机制

冲动是魔鬼,但冲动也会让角色更有血肉。

 

所以,我添加了一个愤怒机制,来模拟这种情绪上的冲动。

 

试想一下你被招惹急了会做什么?气哭了?确实,有时候会这样。但是更多的时候,你会想把对方胖揍一顿渲泄这种愤怒。

 

因此,愤怒机制在系统中起到的作用就是强化伤害输出的决策。

d5Yhx2WZgedouPtCt1qG.png

愤怒与策略行为的关系

 

那么愤怒如何被积累呢?这里使用的设定是:当一个单位受到攻击后,会增加愤怒值;同时,单位每回合行动后,会降低一些愤怒值。

 

| 差异性角色

综上所述,当我们在创造AI时,可以通过调整上述三者策略的比例,来塑造出有差异性的角色。

 

比如:一个制造仇恨策略比例较高的坦克,和一个造成伤害策略比例较高的坦克,它们在一场战斗中的表现可能是:前者更愿意保护队友,而后者则更喜欢追着对方揍。

 

那么哪种更好呢?

 

我觉得都很好,这就好比生物多样性,如果地球上只有人类,那我们的生活该多么的枯燥乏味,甚至无法生存。

 

所以我们要保护生态环境,爱护我们共同的家园。

0780SaI993GU724pv1qB.png

世界自然基金会 (图源网络)

 

| AI系统的设计

其实,这个AI系统的设计非常的简单,我们拆开来看。

 

◇ 战斗行为系统(BattleBehaviourSystem)

每一个参与战斗的单位,都有一个战斗行为系统。

 

战斗单位通过这个行为系统,来决定下一步的行动,比如朝哪移动、向谁发动攻击、或者恢复谁的生命值等。

 

但是战斗行为系统本身并没有什么计算能力,它只是组织了一个信息环境,真正处理信息、产生具有参考意义信息的家伙,是系统装配的战斗行为计算芯片

 

◇ 战斗行为计算芯片(BattleBehaviourChip)

如果你看过《机器猫》,也许还记得在有一集里他拿出了一个“能力磁带”,只要把这个磁带插到身体里,你就会掌握一种能力,比如秒变棒球手、摔跤手、哲学家等等。

OMvU6TUgJA0PKXtwykR9.png

陪伴成长的蓝胖子 (图源网络)

 

战斗行为计算芯片跟这个很像,如果一个行为系统装配了某种芯片;那么当这个单位需要决策下一步行动时,芯片就会结合系统所提供的信息环境,为其列出所有可行的行为,并且为它们打分。

 

当然,一个行为系统可能同时装配多种不同种类的芯片。

 

◇ 行为对象(BehaviourItem)

行为对象就是芯片计算出的行为信息的载体,它记录了这个行为针对的具体目标,以及行为的类型(伤害、嘲讽、治疗)等。

 

◇ 行为调节器(Adjustor)

有时候我们需要微调行为对象中的得分。比如,我们得到了伤害芯片为我们计算出每个目标的得分,但是在做决策前,某个行为调节器忽然想提醒我们应该优先照顾下对方的治疗,那么它就会适当调高对这个治疗的行为对象的得分,同时调低对其他角色的行为对象的得分。

 

当所有调节器工作完毕后,系统将会根据这些待决定的行为对象,制定决策对象。

 

◇ 决策对象(DecisionItem)

制定决策是一个计算具体方案的过程,比如移动到哪个格子,是待命还是使用哪个技能;而决策对象记录了这些计算的结果,战斗单位最终根据这个结果,来完成一次行动。

 

我们可以通过下图更直观的了解行为系统的工作流程。

H98dy4NEKeuUS6ZjxvjA.png

行为系统工作流

 

 

以上就是战斗行为系统的简单介绍,那接下来我们思考一个问题:如何验证系统的有效性;或者,当我们调整了用于驱动行为的数值如何直观的看到反馈

 

| 对结果进行分析

事实上,我们可以在每次调整完数值后,安排一些AI加入战场进行实际作战。

 

通过观察他们在战斗中的表现;以及,分析每个单位在决策时输出的Log,可以在一定程度上达到检验系统有效性的目的。

We3YA7rKHvDKLjD1lvPc.png

一个战斗单位行动前各行为的得分

 

 

但是,这并不是一个好的方法。因为调整数值只是修改了产生决策的范围;而AI在决策上的变化,是很难在一两次的战斗中,通过观察过程捕捉到的。

 

下面,我们就尝试通过对战斗结果进行数据分析,捕捉数值调整后的反馈信息,来验证系统的有效性。

 

首先介绍一下测试环境,创建两只配置完全相同的队伍(Team_1和Team_2)。每队分别配备一名坦克,一名治疗及一名输出。

iAvWOAfFsKUtiCSC2oqk.png

两只队伍的角色配置以及角色关键数值

 

 

sY7yNACfukHkzIa6O4YQ.png

角色所装配的技能

 

 

为了尽量抵消行动次序出生位置可能对结果带来的影响,我们采用每场交换优先行动权,以及全员、全地图随机初始位置的方式,进行500场自动战斗。

 

自动战斗的逻辑我们之前已经完成了,所以这个过程是很快的。

 

vEX8MOsV7hkmh0tPB57S.gif

500场自动战斗计算

 

Dan22jorW0mZjIxL52eb.png

500场自动战斗后,双方的获胜情况

 

 

可以看出,在同样的队伍配置下,双方的胜率是很接近的。

 

接下来,我们调整一些AI的参数,尝试模拟一些特殊类型(个性)的战斗角色,看看战斗系统会给我们带来怎样的反馈。

 

◇ 靠谱的坦克

增加Team_1坦克的嘲讽策略比例,再次对战500场后,与调整前的战斗结果进行对比。

 

0NSIGMpQhj7IaTqQzWwS.png

提高了嘲讽芯片的决策系数占比

 

3MYNdJWypoLztn7RznWM.png

Team_1坦克使用技能的对比

 

bcVKkwYj6eEY3J0rUzFw.png

输出伤害及承受伤害的对比

 

E7nrQENVYrNik9xPNzMN.png

双方获胜情况对比

 

cko1UpEVfb61P2z4hTNO.png

 

Team_1角色场均死亡次数对比


 

可以看出:

坦克使用伤害技能频次降低,使用仇恨技能频次增加,输出绝对值及输出占比减小

 

但这提高了队伍的整体胜率

 

原因可推测为,坦克更好的保护了输出及治疗,减少了他们受到攻击的机会及死亡次数,增加了他们输出伤害和治疗的时间,进而影响了整体胜率。

 

◇ 终结者

为Team_1的近战Dps的伤害芯片增加杀手调节器,使其成为“终结者”,他(她)会优先考虑攻击濒死目标。再次对战500场后,与调整前的战斗结果进行对比。

btH0SmViSQr1xSJj6f6O.png

输出伤害的对比


 

Upf368WVVLgcfGfck2Of.png

场均击杀数量的对比


 

JeRctrKLWgrw8Tjs8egL.png

双方获胜情况对比

 

可以看出:

由于属性和所使用的技能都没有变化,所以终结者的输出伤害变动很小;但是他的击杀数量明显增加(抢人头)。

 

尽管队伍胜率增加了,但是队友都很讨厌他。

 

◇ 治疗压制

为Team_1的近战Dps所拥有的伤害芯片增加了职业权重调节器,并设置为治疗压制模式。从此,他莫名其妙的对敌方的治疗产生了难以言喻的奇妙情感,并一直重点照顾。


 

jJAr0a5HMjkNKJmw9ACR.png

职业权重调节器的设置


 

p62aK1PYi86CEsK5iPO1.png

Team_2接受治疗对比


 

7MG779B0WwohTsBJGKJ5.png

Team_2 治疗承受伤害的来源及击杀来源的对比


 

zKrO0iEve46UZjzZzTjH.png

双方获胜情况对比

 

可以看出:

治疗被对方输出特殊照顾,直接减少了她的治疗总量;而且由于自身不断遭受攻击,治疗把技能更多的用在了自己身上,无暇顾及其他队友,进而降低了整体胜率。


◇ 职业保镖

Team_2的坦克会优先保护己方治疗,只要看到她被揍,瞬间宠妻狂魔附体。


 

JsyY1eej4vcjVWIxE5Jf.png

Team_2胜场存活率及剩余血量对比


 

eRUOkUmUwlG0vIq74s5S.png

双方获胜情况对比


 

183lgZ4KQMwuWLfZhpmI.png

Team_2接受治疗情况对比

 

可以看出:

Team_2的治疗得到更多保护,产生的治疗量增加,胜场存活率提升,提高了整体战斗力。


 

N0v7rhhLx34pwnwAu4i0.png

《保镖》海报 (图源网络)


 

后来在一次线下聚会时,坦克发现这个“治疗妹子”居然是个汉子...

 

◇ 职业杀手 vs 职业保镖

Team_1的近战Dps为治疗压制 + 终结者,Team_2的坦克为治疗职业保镖。

 

结果…

 

你猜。


 

oiLlVL7YJ1ervbzkfKcR.png

《王牌保镖》海报 (图源网络)


 


 

| 写在最后

至此,调整AI系统的决策方式篇就介绍到这了。

 

如你所见,本篇所展示的例子,都是单因素实验;而且角色类型、技能、数值结构都非常简单。对比那些态度认真、具有复杂技能、数值等设计的游戏,可能不太具有说服力。

 

但本篇想要做的仅是对“用数值影响AI决策”的一种尝试,而且这种影响是可以在后期的数据分析中得到反馈的,从这点上讲,目的已经达到了。

 

下一篇将会对AI系统的设计做一个简单的总结。

 

最后,需要指出的是,前面提到的《机器猫》,后来已经改名为《哆啦A梦》了。

 

愿不忘初心。

 

下回见。

 

非常感谢您能读到这里,详细的代码可以移步Github(https://github.com/elsong823/HalfSLG)下载。

 

文章会在我的公众号 偶尔学学Unity 中不定期更新,欢迎关注,谢谢。

pwdSDuOTxi1fCMta3q1L.jpg


 


 

  • 允许他人重新传播作品,但他人重新传播时必须在所使用作品的正文开头的显著位置,注明用户的姓名、来源及其采用的知识共享协议,并与该作品在磨坊上的原发地址建立链接
  • 可对作品重新编排、修改、节选或者以作品为基础进行创作和发布
  • 可将作品进行商业性使用

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

标签: