ACT技能编辑器的制作经验分享
- 作者:admin
- /
- 时间:2018年06月20日
- /
- 浏览:15102 次
- /
- 分类:厚积薄发
作者通过个人的项目经验,复盘了ACT技能编辑器制作全过程,并对细节部分进行了经验总结,十足干货分享,推荐大家收藏了解。
技能编辑器功能演示(Unity版本为5.6.4p4)
缘起
我在一个新组建的团队里,只有一个策划兼制作人,加我一个客户端(公司美术内包)。我们需要在一个月内快速出一个ACT动作的Demo,Demo需要有至少三个角色和若干小兵,并通过评审会正式立项。当时我并没有做过这类ACT游戏,对这类游戏所知甚少,在策划的讲解,以及恶补了一些文章后,我们定下了计划:
1、在半个月内做一个技能编辑器,要支持编辑动作每一帧的攻击受击框,配置按键指令的招式转换,以及各种攻击数据的配置;
技能编辑器提高后续策划工作效率
2、同时制定美术制作动作的规范,以及我们如何切分动作,动作的复用和衔接;
3、第三周做Runtime的战斗逻辑,第四周整合资源,编辑器的配置,出Demo包。
计划
时间紧,任务重。我给自己的任务是不加班完成,并尽可能将编辑器功能提前完成,给后续留出更多的调整和DeBug的时间,因此需要:
1、尽可能和新策划搞清楚需求,做Prototype的推演,推演Editor下如何配置,Runtime如何执行。有经验的程序,会花更多的时间在前期的需求整理和逻辑推演上。
2、和美术梳理工作流程,让美术可以立刻开始做事情,后续能和我们的编辑器很好地对接。所以,在Demo阶段,美术只提供模型Fbx和动画Fbx,剩下由程序整合。
常用的动画分割方式
分析和选择
接下来,有几个技术点,需要做出选择:
1、是使用Animator 的状态机来做逻辑,还是自己做切换逻辑?
最终选择了自己做逻辑切换,核心就是工作流可定制。
Animator状态机自动生成,最简化,不包含任何逻辑和数据
2、是使用Unity的GUI来做编辑器,还是UGUI做?
最终选择用UGUI,主要是怕用GUI时间来不及。另一个原因是我希望策划能在一个技能编辑器下做所有的操作,流程一体化。不要那种在A Prefab上挂个脚本,再在B Prefab上挂个脚本,最后把A和B拖到C Prefab脚本的Field上这种编辑方式,这不利于策划理顺思路。(可对比白鹭引擎一堆Editor和Unity All In One)
3、如何做编辑器数据的序列化?
最终选择了自己做序列化,最主要的是数据和资源分离,以及热更新。
4、是使用Unity自带的Collider(物理系统)来做碰撞,还是自己做碰撞检测?
因为我们是横版游戏,所以,按传统的格斗游戏做法,只需要做Box,而且是不需要旋转的Box,自己实现的复杂度大大降低,那肯定自己做更可控。
简单总结下选择方案的思路:
- 没有方案是对所有项目都合适的,选择适合自己项目类型以及开发周期,人员配置的方案;
- 要着重考虑数据和资源的分离,热更新。考虑好和美术、策划的衔接工作流程,这些比逻辑本身更重要;
- 可控性和开源,尽量使用自己熟悉和可控的实现方式,尽量选择开源的插件和工具。
关于ACT游戏,我的理解
我作为非ACT游戏玩家,我理解的ACT游戏和MMORPG,ARPG这类游戏的战斗表现上,区别如下:
所以,ARPG是介于ACT游戏和MMORPG之间,ARPG和ACT游戏,有着重大的区别(按策划的话:市面上太多所谓动作游戏,只能说是ARPG)。
ACT游戏需要具备:
- 快速的操作反馈,需要玩家衔接好操作,才能输出最大化;
- 招式衔接的丰富,不同招式下,不同时刻,不同按键,要切换到不同的招式;
- 打击反馈的丰富,被击需要有动作反馈,轻中重,浮空等各种击中方式,被击者需要不同的动作反馈。
- 以上是一个非ACT玩家,做为程序开发者的理解,方便我区分当年做MMO的经验。
开动:以数据为基础来搭建框架
编辑器的目的是为了数据,所以,对于技能(这里只包含按键触发的主动技能)的数据组织如下:
角色数据图
ActorCfg:角色数据的根,包含所有角色相关数据;
ActorAttr:基础数据,包含资源Prefab ID,移动速度,重力,指令起始招式ID等;
指令
ActInfo:一个动作的信息,对应美术制作的一个动画(Animation);
动作列表
FrameInfo:每一帧的信息,一般包含攻击,被击框的信息(Position,Scale),以及一些复杂逻辑使用的标记;
动作游戏,需要给攻击和被击都打上框,没有被击框的帧,就不会被击中。
SkillInfo:招式信息。每个招式可以由一个或多个动作(ActInfo)组成,并可以选择动作的帧范围,这样最大程度地复用美术动作,并可以由策划自由发挥,组合出新的动画;
不同的ActInfo(Animation)组合出不同的招式
BoxInfo:不同类型的Box,不同信息。比如攻击,被击,霸体等不同Box的信息不同;
攻击类Box数据
HitInfo:攻击类Box,击中以后的数据配置;
当击中后,需要的数据,根据策划的需求来
ChangeCtrl:切换招式的数据。比如在帧范围(0~10内)触发了指令(Up),切换到招式xx;
Change To 招式 ID
SkillCtrl:各种技能处理,播放音效,特效,设置速度等等;
各种控制
Trigger:各种判断条件,条件达成,才会执行ChangeCtrl或SkillCtrl
各种Trigger
以上是主要的数据模块,ActInfo主要保存每一帧框的位置缩放信息,SkillInfo保存各种ChangeCtrl和SkillCtrl,并用Trigger来做为生效条件。后续按策划需求对技能编辑器的扩展,更多是SkillCtrl的添加和Trigger的添加。
通过这一套技能编辑处理,策划可以配置出丰富的表现效果。只要数据组织好了,同一数据,有不同的表现形式,这也是基础的MVC的适用。
对于习惯使用类似TimeLine编辑方式的,可以用Frameline方式(Gif压缩有点糊了)
序列化数据
编辑器,最重要的是数据的读写,也就是序列化和反序列化。
之前已经说明,我不使用Scriptobject和Prefab上挂MonoBehaviour来序列化数据的原因,不再赘述。现在放在手边的选择有两个,一种是序列化为文本(XML,JSON),一种是序列化为Bytes。
我最先是序列化为XML,因为我认为XML比JSON可读性强一些,刚开始我可以先手动写一个XML数据,Deserialize为对应的Class,等编辑器基本成型以后,再补上Serialize即可。
这样,我只需要设计一个根据Tag反射来自动化处理的方式即可(当时没仔细找,应该此方式有现成方案)。
通过Tag,可以写一套通用的序列化反序列化处理
XML序列化在前期的好处是,编辑器不稳定,数据经常错误报错,可以手动修改XML的数据,方便测试编辑器Bug,以及调试功能。XML还有很好的可读性,以及版本管理方便Merge。
但是当我们编辑器稳定后,XML的劣势就显现了:
1、序列化反序列化性能差;
2、这里需要给一些不支持String化的数据做支持(Color,Curve等);
3、序列化依赖变量Name,如果我们重构改了变量名(重构名字是常事),数据就丢失了。
经过调研,我们选择了用Protobuf来做序列化,直接解决了1和3的问题。需要了解Protobuf详情的请自行Google。
Protobuf来序列化,Protobuf的Tag
对于2里面的问题,需要做一些处理,将其Protobuf化
将Color Protobuf化
PBColor的使用
再结合AdvancedInspector插件(后面介绍)来使inspector下支持和原来一样的显示。
至此,基本上解决了序列化和反序列化的问题,最后我们将每一个角色数据,序列化,存为一个.Bytes文件。(带来的副作用,即不方便Merge,这里只有策划通过规范提交修改的流程,减少冲突,目前我们遇到很少)
一个角色对应一个文件,由编辑器读写
配合AdvancedInspector提供的UDictionary,我们可以方便地做Dictionary的序列化。
UDictionary
UDictionary的使用
到此,我们需要介绍一下,帮了大忙的插件Advanced Inspector(现在似乎有了更好的Odin):
https://assetstore.unity.com/packages/tools/utilities/advanced-inspector-18025
具体使用我就不说了,大家可以去看他的Sample,对于在Inspector上做东西,方便很多很多。
SkillCtrl 和 Trigger的设计
在总体设计好之后,新加的技能方面的功能,主要集中在SkillCtrl 和 Trigger的添加。
这里在语义上是:当XXX的时候,执行YYY。 XXX就是Trigger,YYY就是SkillCtrl 。比如策划可以配置:
- 当0~10帧时,播放技能特效;
- 当10~20帧时,并且是击中状态,播放技能特效;
- 当20~30帧时,震动屏幕;
- 当20~30帧时,角色在浮空状态,添加人物残影;
在设计上,SkillCtrl和Trigger,都是这样:
1、定义一个TriggerType
Trigger Enum
2、定义Trigger的基类
Trigger Base
3、之后扩展,就是继承基类,加上配置数据,Override isTrigger方法,处理自己的条件逻辑。
Trigger Implement
SkillCtrl,主要包含一列Trigger,所有的Trigger都为True,就返回True。这里没有设计or的逻辑方式,Trigger之间,都是And的方式。
对应Runtime逻辑,一个SkillCtrl cfg,对应一个ctrler
Runtime Ctrler Base
扩展的时候,实现对应的Ctrler即可:
对应的播放声音 Ctrler
大部分游戏,需要设置逻辑主循环,在每一个Logic Tick,去检查Trigger,Trigger都为True,执行对应的Ctrler,即可。这里的Logic Tick,即对应编辑器里面的一个帧,同一概念。
接下来是一些小的点:
1、这里有一个小Trick,就是类命名用"_"分隔,前半部分一样,后半部分区分具体实现,可以通过反射来获得Instance类,以免做工厂,或者Switch case。
ActorSkillCtrlerCfg_Base cfg = U3DUtil.CreateClassByBaseType<ActorSkillCtrlerCfg_Base>(ctrlType);
2、在这样设计的过程中,遇到了一个问题,就是Unity的Inspector。声明是Base Class,但是赋值了Child Class,Unity的Inspector还是显示Base Class 的数据。
例如我希望在编辑器里点任何一个Ctrler,都显示对应Ctrler类型的数据。
资源的Ctler
对应的代码
Unity默认的Inspector,只会显示申明的类型ActorSkillCtrlerCfg_Base,而不会显示对应的特效数据。
这里解决方案很简单,引入Advanced Inspector即可,插件能自动显示真实Type的数据,这是Advanced Inspector帮助解决的最大的问题。
思考:每一个功能模块,我们要处理好完全不设计和过度设计的平衡,特别是一开始,不要过度设计。花时间理顺需求,尽量找准扩展点,把扩展点处理好,后续就是往上搭积木了。这个过程中,必然经历几次重构和优化,没有一次就做好的设计,重构是程序的核心技能。
编辑器和Excel表数据的配合
当我们开发Demo的时候,尽可能求快。角色的数据,我们就直接在编辑器里配了,比如攻防血,技能每一个Hit的伤害,招式的CD,消耗的SP等,也并未考虑招式升级了,基础伤害提升等,这些也不是编辑器应该关心的逻辑。
当项目正式化之后,我们需要解决的,就是数据,策划是配置在Excel里的,我们需要整合Excel数据和编辑器数据。
对我们来说,比较麻烦的是,我们结算伤害,并不是以一个技能为一个单位,而是以每一个Hit,一个技能,策划可能配置多个AtkBox,一个AtkBox,可能产生多次Hit,但是,我们不可能给每个Hit配置一个伤害,数值策划配置到这么细,他们会崩溃。所以,策划的Excel表,是以技能(招式)为单位,配置一个伤害。
数值配一个角色,某一个招式动作的总伤害数值
而技能编辑策划,在技能编辑器里,配置每一个Hit,对应这个伤害的百分比:
比如这个招式,策划配整体伤害1000,某个Hit这里配置0.4,最终结果就是1000*0.4 = 400。通过这种方式,将数值策划从编辑器中解脱出来,他们无需关心有几个Hit,只需要处理整体效果,技能编辑策划去将所有Hit的系数分割。当然,我们数值计算很复杂,这只是初步基础数值。
思考:这里其实是想说,将逻辑和数值分开来,各自关心各自的东西。这样,我们将Prefab(View),逻辑(技能逻辑),数值(Excel配表)都区分开来,按照一定的规则,在Runtime时候结合。
经验教训:
1、没有做整体的Undo和Redo功能,因为做Demo的时候,整体只有两周,实际大概一周半做完。没有时间设计整体的Undo,Redo。后续根据策划需求,解决了部分Copy,Paste,以及依靠Advanced Inspector的功能,做到了Inspector部分的Copy,Paste,也算基本不影响策划的使用。但仍然算是一个不足。
2、战斗整体预览,做得不够完整。目前在播放器里,可以在Play 招式的时候,对应播放特效,声音。但是不能所有SkillCtrl整体模拟。 之前想过在Editor里面跑一个简单的Runtime Battle,只包含当前编辑的角色和一个NPC,让编辑和预览能够无缝衔接。但是处理起来,有点麻烦。 现在的做法是在Runtime 的GM菜单中给一个接口,当打开技能编辑器编辑保存以后,将Runtime Cache的配置清空并重新打开战斗,选定的角色就会重新Load 新保存的配置。虽然这个方法不够完美,但也极大提高了策划的速度(以前编辑好一个,需要重新Run游戏,现在可以在游戏中实时更改,再进入战斗就更新),帮助策划提高工作效率,是程序责无旁贷的责任。
- 有些部分设计得不够友好,策划配起来,有点麻烦。例如配置子弹的逻辑,目前做的不够好。
- 我不想做一个大而全的,能通用的编辑器,我只想理顺思路,当我们下次做项目,或者类似东西的时候,能够在现有的基础上,通过裁剪和重构,快速得到一个符合项目需求的编辑器。(所以我的编辑器,不做任何Unity版本兼容)
现有编辑器,可以支持格斗,ACT,ARPG类游戏,如果做MMO和RPG,那就要裁剪到过于复杂的部分,简化即可。如果做点跑酷呢?那要这编辑器就没意义了,一切都要根据自己的项目来,不是越强大越好。
最后总结:
- 当我们需要快速出Demo的时候,更应该理顺思路再动手,切忌上来就编码。把可能的难点先测试搞定,之后就顺手了;
- 重构,不要怕重构,在合适的时间,做合适的重构,是我们程序的核心技能;
- 组织好数据,让数据和美术资源分离,不要让美术资源的变化,干扰你处理数据的工作流;
- 帮助策划提升效率,是程序能力的体现;
- 做编辑器,要站在策划的角度,他们是用户,自己要用,才会发现问题,Eating our own dog food.
这是侑虎科技第407篇文章,感谢作者Gordon供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。QQ群:793972859(原群已满员)
作者知乎:https://zhuanlan.zhihu.com/p/38001896,作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!
厉害,我自己在上个项目也写了个编辑器,最麻烦的还是策划需要有一个npc跟怪物这种做打击的查看,这块我也没弄,还有你说的弹道跟持续性技能也是技能编辑器相对头疼的东西。不过你的思路相对清晰好多。厉害