基于Unity3D 的角色动作游戏战斗系统研究与实现

2023-05-17 03:16何柳青
电子技术与软件工程 2023年5期
关键词:状态机怪物动画

何柳青

(广州工商学院工学院 广东省广州市 510850)

近几年计算机图形图像技术的提升令游戏行业飞速发展,游戏公司只要在经费充足情况下便可开发出高画质的游戏。然而在游戏画质同质化的怀况下,游戏核心内容设计则成为游戏差异化的重点内容之一,而战斗系统则是角色扮演游戏里几乎不可缺少的内容,它与玩家的长期互动环节有紧密关联。战斗系统是角色动作游戏的核心内容,是游戏的直观表现之一,同时也影响到游戏的整体设计水平。

战斗系统有其完整的流程框架及设计标准,从前期的策划到模型资产的生成,再到后期代码编写及测试,从表面上看这是一个线性流程,但在项目中可以进行非线性编辑。例如在游戏开发过程中发现角色战斗机制某个环节需要调整,则可以重新修改机制策划表格数据,修改代码以满足项目需要。

1 游戏角色属性机制

如图1 所示,游戏角色的属性是整个游戏的基础数据,它直接影响到角色在游戏中的发展。如果游戏中存在多种职业,则角色属性根据不同的职业设定不同的基础属性,如生命值、基础攻击、基础防御等。除此以外,还存在辅助属性,如闪避、暴击、技能附加状态等[1]。

1.1 基础属性

基础属性是战斗系统的根基,攻击、防御、生命等参与最直接的逻辑计算。比如我方角色实施一次攻击,根据敌方角色的防御来扣除一定量的生命值,这是最原始的计算方式,虽然最终不会直接使用这种方式,但它是游戏中一切算法的基础。基础攻击方式一般不宜过多,电脑端大型网络游戏会限制在十种以内,移动端游戏则一般限制在四种以内,但移动端游戏可能会由基础攻击衍生出分支攻击,以此来增加游戏可玩性。

1.2 辅助属性

辅助属性通常起到对基础属性的修正作用,这类属性也会并入攻防伤害计算公式中。战斗基础属性是一切攻防的底层基顾,但这种基础计算会令玩家觉得枯燥乏味。如果在此基础上加入随机性,则玩家有一定机率战胜比自己稍强的对手,实现越级挑战。当玩家触发辅助属性中的其中一个及以上数量的分支属性,会获得更高的回报收益,这样会较大程度增加玩家的挑战欲望和成就感。

辅助属性中部分分支属性不能过多分配,例如暴击、闪避以及部分技能会产生多倍攻击和令对手无法命中,这样虽然会增加游戏的趣味性,但类似这些效果只能控制在短时间范围内,否则会破坏机制平衡。

2 游戏战斗框架设计

游戏战斗框架主要涉及到玩家、怪物、NPC 的行为,以及由此行为而导致的反馈。本案例把战斗框架分成三个模块:动画模块、行为模块、事件反馈模块。

2.1 动画模块

动画模块实现了角色的动画与动画控制功能,例如角色行走、跑步、飞行、攻击等行为,而动画控制功能则是精确控制角色所有动作的播放,当鼠标或键盘输入指令时令角色播放相应的动作。该模块是为了让玩家输入指令获得直观的反馈,也是游戏底层和玩家的直观互动,而所有角色动画都由状态机实现。

2.2 行为模块

行为模块分为玩家行为、NPC 行为、怪物行为。在游戏的虚拟世界中,角色并不具备现实世界中生物的思考能力,这就需要给模型赋予一定的预置行为,最后把这些行为封装成模块,提供接口。例如NPC 处于站姿且等待玩家互动的状态,野外的怪物在站岗监测敌情的状态。这些行为均未触发某些特定事件,处于无限待机循环的状态。

2.3 事件反馈模块

事件反馈是基于行为模块在触发某事件后作出的进一步行为,例如地图上的怪物在玩家进入其监测范围内后,将对玩家采取何种行为,如召集同伴实施群体攻击,或者实行其他攻击方式。不同怪物敌人有不同的行为反馈,但其中必有其共同的行为,如个体攻击方式或群体围攻,将行为拆分成小模块封装成接口可在后续程序加以调用。战斗框架如图2 所示。

图2: 战斗框架

3 游戏战斗系统平衡

在游戏战斗框架设定后,就需要考虑战斗系统的平衡。游戏的平衡关系到整个游戏能否持续运作下去,玩家在完成某件任务后获得的奖励要与任务难度成正比,如果奖励过于丰厚则会破坏游戏平衡性,从而令游戏无法长久运作[2]。

3.1 角色的等级成长平衡

角色扮演游戏的角色成长分为两种:升级型和无等级型。本项目使用的是升级型成长模式。升级型的成长以角色等级、装备等级、道具等级、技能等级提升作为主要标准,其中角色等级限制了其他部分等级的提升。如果角色等级不提升则其他部分等级也无法提升,也无法遭遇等级更高的怪物敌人而导致游戏无法继续玩下去。

3.2 游戏战斗系统战力平衡

本项目设计的游戏挑战难度主要针对玩家与电脑怪物敌人的战斗,它亦是ARPG 游戏需要重点思考的问题。如果游戏中怪物的战力等级超越玩家越多,则玩家的挑战难度越大,反之越小。当玩家战力与怪物差距在一定的小范围内时,玩家会被战斗过程吸引。玩家角色与怪物敌人战力平衡模型图如图3 所示。

图3: 玩家角色与怪物敌人战力平衡模型

从图3 坐标图可见,玩家角色和怪物等级最小值为1,当玩家角色战力等级远高于怪物时,玩家就会觉得战斗难度较低,反之会觉得战斗难度过高,两者均不会在心理上产生成就感,同时也不会保持游戏兴奋度。所以,游戏设计尽量让玩家处于这种状态,利用地图区域限制的方式来划定怪物相应的等级,以此保持对游戏的兴奋度。假设在新手村地图的怪物等级是1 至4 级,而玩家角色在该区域最快能提升至6 级,当玩家角色升至6 级时,击杀4 级的怪物获得的经验值将大幅下降,欲想快速升级则必须进入更高级的地图区域。

除了主要任务的战力平衡,需要设计少部分高难度的任务,如击杀特定的首脑怪物。这些任务有更高战力等级的怪物敌人,任务奖励也更高。这种风险高、奖励高的任务通常是为操作水平较高的玩家而提供,这类玩家数量较少,并不影响游戏整体平衡。

令玩家长期保持游戏兴奋状态是游戏设计必须要做的环节,但兴奋时间过长也会给玩家带来疲劳感。人的大脑在长时间兴奋时必然会精神高度集中,当战斗任务结束后则会感觉无法继续这种状态,精神高度亢奋会消耗大量精力。因而,玩家高强度战斗后则需要适当的休息,可以适当设计一些休闲小游戏或建立安全区供玩家休息等。

4 游戏战斗流程设计

游戏战斗流程结合了前面所提到的几方面,它并非单独存在。整体而言,战斗流程是从预备状态到结束战斗的过程,它可以发生多次循环。同一款游戏中针对不同敌人可以有不同的战斗机制,以此区别各种不同类型的战斗。战斗流程主要由以下几个环节构成,其中攻击状态、伤害计算是战斗流程中的两大核心环节。三种伤害类型包括基础攻击伤害、主动技能伤害、被动技能伤害,均是封装好的模块,战斗中产生的伤害就是调用这些模块来计算数值,这些数值会影响战斗结果的评价,从而影响战斗胜利时的奖励[3]。战斗流程如图4 所示。

图4: 战斗流程

从游戏设计的角度来看,战斗系统是为了让玩家体验战斗乐趣而设计的,即玩家通过战斗过程而获得愉悦的体验。对于不同的玩家有不同的体验,战斗流程的设计主要是迎合绝大部分玩家,不能为了少部分特例玩家而破坏大部分玩家的体验。平衡不同玩家的体验是游戏战斗流程设计的重点环节,对于移动端游戏,则需要内测玩家反馈回来的大量数据和意见才能做好平衡的策略。

5 战斗逻辑及属性设定

5.1 战斗伤害逻辑设定

战斗伤害逻辑被包含于战斗流程中,它主要表达战斗过程产生的个体伤害关系。

即时战斗和回合战斗是动作角色扮演游戏的两种战斗模式,它们均要遵守战斗流程提供的战斗伤害逻辑,本项目使用了即时战斗模式开发战斗系统。即时战斗和回合战斗在制作难度上有较大区别,即时战斗的角色可能在同一秒中受到不同对手发出的攻击,以及不同的技能负面效果,综合各种因素计算出即时所受到的伤害数值。即时制可以多个单位同时战斗,需要计算多个线程,并发压力大,对程序编写的要求高。即时战斗模式伤害计算的基本逻辑是通过技能基础伤害、防御减伤、技能buff影响等因素来综合计算[4]。战斗伤害逻辑关系如图5 所示。

图5: 即时战斗伤害逻辑

5.2 角色属性公式

战斗流程提供的是战斗的整体框架和逻辑,而战斗中产生的数据则是由公式来计算,公式中包含了角色属性和伤害计算内容。游戏中的战斗算法公式可以根据项目需要自行定义,但不同项目的公式算法差异不大。

5.2.1 角色生命值属性公式

角色涉及战斗系统的重要属性是生命值,它直接参与战斗数据的计算。游戏角色的生命值有多种计算方法的公式,但基本的思路框架不变。本案例生命值计算公式设定如下:

角色总生命值=(原始生命值+等级生命值+装备生命值)×(1+装备生命值百分比)

假设某角色出生时是1 级,其基础生命值为500,等级提升到2 级时增加200 生命值,装备固定生命值100,装备能提升角色生命值的3%(装备的特殊属性),则该角色在2 级时生命值为:(500+200+100)×(1+3%)=824。

除此以外,角色在某种技能增益下还能短时间内提高生命值。当角色生命值为零时,角色死亡[5]。

5.2.2 技能输出公式

角色除了普通攻击外,通常还有技能的施放,此算法是针对伤害技能而设计,有需要时可以在伤害计算中调用。技能公式大致框架为:

技能输出伤害值=技能原始伤害值×(1+技能伤害输出比率+角色增益比率+目标状态比率)

技能原始伤害值是显示在游戏属性面板中的,玩家可以查看。而技能伤害输出比率、角色增益比率等三个属性玩家无法查看,属于隐藏属性,主要是为了方便程序员后期调整游戏数值平衡[6]。需要注意的是此技能输出伤害值仅为单方输出数值,未计算敌方防御和其他参数,非敌方最终受到的伤害数值[6]。

5.2.3 公有伤害输出公式

公有伤害输出公式主要有三种:减法、乘法和除法。可根据不同项目来定义输出公式。

减法计算是最直观的,计算方法即攻击减去防御得出伤害值,如:

敌方受到的伤害值=攻击-防御

减法公式的最大弊端是当防御大于攻击时总伤害等于零,在游戏中零伤害的数值是不被允许存在的,伤害值至少是1。

在本案例中使用的是乘除法,这种算法最终结果不会出现零伤害值的现象。其中R 是自定义的一个常数,公式的核心逻辑是计算出减伤率,并用一个常数来调整伤害输出的平衡。利用常数来调整伤害输出数值是项目中常用的手法,更重要的是在游戏后续更新中可以进一步调整角色战力参数[7]。

敌方受到的伤害值=技能输出伤害值x [1-防御/(防御+R x 武器级别值)]

乘除法计算公式可以用在物理攻击上,也可以用在法术攻击上,只是两种攻击的收益加成略有不同,但整体思路框架不变。此算法调用了5.2.1 的技能输出伤害值,将其与武器级别值纳入计算,计算敌方最终受到的伤害值。

6 战斗系统关键功能设计与实现

战斗系统的关键功能主要包括角色动画状态机设置和战斗脚本算法,这两个环节互相关联,缺一不可。

6.1 动画状态机

游戏中的角色动画可以通过给角色预制体的Animaiton 组件添加多个动画片断,以此来控制角色的不同状态动画。但Animaiton 组件不能提供动作动画之间的过渡转换,也不能表达动作之间的逻辑关系。而动画状态机(Animator)则可以让游戏设计师减少大量的代码编写工作,仅需要极少的代码即可实现不同状态的转换。

单个角色通常都有多个不同的动画片断来表达不同的行为,如角色在待机时人体常规微动作、行走和奔跑时的动作、攻击和防御时的动作等。角色在状态动画切换是有条件限制的,动画之间并非随意切换,例如角色具有连招的攻击动画,那么第二段攻击必须建立在第一段攻击的基础上,否则无法激发该动画。状态机可以创建一个Animator Controller 来设置动作的关联过渡,如图6 所示。

图6: 角色动画状态机设置

状态机中Any State 节点代表各个状态随时都可能跳转至它能指向的其他状态,可以将其视为一个监听器,同时也是所有状态的总控制节点,在一定条件下它可以让任意一个状态播放动画。Any State 节点非强制性使用,在本项目中首先将Idel 动画拖入状态机,Entry 节点则默认将其作为初始动画,该初始动画会被映射到Any State 节点中,使其具有Idel 动画的属性。当动画状态节点数量较多时,Any State 可以起到更好管理所有状态动画的作用。

状态机动画的另一种管理方法是分层管理,表面上可以实现动作组的高效管理,但本质上连线数量仍然不变,并未减少工作量,本项目不采用分层管理的方法。

状态机的动画节点根据需要设置过渡连线(Make Transition),同时需要设置相应过渡条件(Conditions),当前置动画满足过渡条件时就会播放下一个动画,如表1 状态机动画触发条件。

表1: 状态机动画触发条件

表中状态机条件类型有Bool 和Trigger 两种,其中Bool 类型参数当达到触发条件后播放下一段动画,动画结束后会切换回待机(Idle)动画,而Trigger 类型条件则只播放一次,通常为攻击或防御类型动画。当第一段攻击(Attack1)播放结束时,再次按下攻击键会继续播放第二段攻击(Attack2)实现连续攻击,第二段攻击结束时如不再按攻击键,则会返回待机(Idle)动画,如继续按攻击键会再次从第一段攻击开始循环。

6.2 攻击技能的实现

从6.1 可知角色攻击按钮分为普通攻击(Norma Attackl)和范围攻周(AoeAttack),当按下普通按钮时,怪物在近距离攻击范围时则会受到攻击伤害,连续按普通攻击按钮则会产生连招效果,对怪物施予多段攻击伤害,而范围攻击则可以在攻击范围内单次对多个怪物实施攻击[8]。游戏战斗操作界面使用NGUI 插件设置,如图7 所示。

图7: 游戏战斗操作界面

设置完操作按钮后,通过代码添加点击事件的监听。玩家在操作角色时是直接对角色输入指令,如有多个角色则一般会设置成预置体,通过C#的UIButton 里的onClik 事件,监听普通攻击和范围攻击虚拟按钮的操作情况。具体代码如下:

6.3 角色动作连招的实现

动作游戏里存在多个技能,不同的技能按设定好的机制形成相应的连招。连招并非只有一套,因游戏本身无法预测玩家下一次按哪个技能键,因此连招具有一定的不确定性。即使玩家不按预定的招式按下技能键,尽管动作衍接不流畅,但也能形成连招,例如奔跑过程中突然发起攻击,动作之间的补帧则由状态机计算完成[9]。

从图6 可知,普通攻击的Attack2 是Attack1 的后续攻击动作,当两个动作按顺序播放时则形成连招。攻击动作Attack1 共10 帧,设置前5 帧为事件Attack2Event1(可触发Attack2),后5 帧为事件Attac k2Event2(不可触发Attack2)。具体代码如下:

连招动作效果如图8 所示,在Attack1 动画前5 帧内继续按下普通攻击键,则会播放Attack2 动画实现连招,反之则回到待机(Idel)动画。

图8: Attack1(左)和Attack2(右)连招动作

6.4 攻击及伤害判定算法

游戏战斗伤害计算有多个环节,在C#中可先定义一个公有伤害类,以便为其他伤害算法所调用,如主角的连招及敌人的攻击等。此处定义血量为300,普通攻击伤害为30,攻击范围为1,animator 为状态机的变量。

当角色受到攻击时,其剩余血量值为:角色剩余生命值=角色最大生命值-受到伤害值。此时若角色剩余血量大于零,则处于受击状态,同时播放受击硬直动画,否则进入死亡状态,同时播放死亡过程动画[10]。其逻辑关系如图9 所示。

图9: 攻击及伤害输出判定

判定角色存活或死亡具体C#代码如下:

7 游戏战斗实机测试

将主角与怪物放置于战斗场景中运行游戏,连续点击黑色NORMAL 普通攻击键令主角发动连招从而攻击怪物,同时怪物也对主角进行攻击。当其中一方先受到攻击则会产生硬直状态,左下角的位移键可使主角移出怪物攻击范围,从而令怪物无法攻击主角。连招效果如图10 所示。

图10: 连招效果

当按下红色ATTACK(AoeAttack)键时,主角发动范围攻击,给予怪物重击效果。如图11 所示。

图11: 范围重攻击效果

经测试,怪物的战力符合玩家角色与怪物敌人战力平衡模型的设计要求,玩家可以在地图中通过配合走位和攻击,从而击杀与自身战力差距不大的怪物。

8 结语

动作游戏战斗系统的质量直接影响玩家的游戏体验,系统的模块之间紧密相扣,形成一个整体。本案例对游戏战斗系统各模块进行了研究与设计,实现了动作游戏战斗系统的主要功能。去除了陈旧的设计思路,从玩家角度出发,优化了战斗系统的平衡性,避免了玩家可能因游戏难度过高或过低从而对游戏失去兴趣,同时也调整了战斗动作,增加了其流畅性,增强了玩家的游戏战斗体验。

猜你喜欢
状态机怪物动画
做个动画给你看
动画发展史
基于有限状态机的交会对接飞行任务规划方法
我是动画迷
Women in the Workplace, Fighting Spam, Money in the Museum, and the Mood for Food
曾被误认为怪物的伞
FPGA设计中状态机安全性研究
基于反熔丝FPGA的有限状态机加固设计
基于VHDL的一个简单Mealy状态机