阶段性开发总结。
Test
Runtime简单演示。
设计架构
Editor
编辑器的核心类SkillMasterEditorWindow,该类负责了编辑器的页面绘制,并持有一个正在修改的SkillClip实例,将SkillClip中的五种数据类型分别绘制出五种轨道,轨道类型的基类为TrackBase。每种数据中的数据内容会以片段的形式显示在轨道中,轨道片段的基类为TrackItemBase,其提供了虚函数Select()等,当选中片段时,会在引擎的Inspector监视器中显示该片段的数据并可以进行手动编辑,这部分由SkillEventDataInspecterBase类负责。
技能表现可视化的核心在于TrackBase类中的虚函数TickView(),该方法会被各不同数据的轨道子类重写。在SkillMasterEditorWindow中,当读取完持有的SkillClip后,创建可视化轨道的同时会同时维护一个当前的轨道列表m_TrackList。另外,技能编辑器持有一个预览角色的引用,这个预览角色可以是游戏场景中的任意一个角色。当按下技能编辑器上的播放按钮时,技能编辑器内部会开始维护一个计时器并执行TickSkill()方法,在不运行游戏的情况下对技能时间轴进行逐帧Tick操作,此时会触发每个Track的TickView()方法,在每个Track的TickView方法中,根据Track内的数据对引用的角色curPreviewCharacterObj进行对应操作(如动画轨道会把当前帧的动画数据采样到角色物体上),从而达到可视化编辑与预览技能片段的效果。
在技能编辑器中修改的数据会实时反应到技能编辑器的TickSkill()效果中,因此可以快速调整与开发技能,最终数据会存储回当前的SkillClip中。对于每个技能,其表现层的行为完全由其对应的SkillClip中的数据决定,无需再在代码中进行编写。依靠技能编辑器可以快速迭代出大量的技能,可维护性较高。
Runtime
数据层面上,由于SkillClip是表现层数据,所以需要往上再封装一层SkillConfig类,用于存储技能的逻辑层数据(如攻击力等),一个SkillConfig持有多个SkillClip,以满足同一技能可以播放多种不同表现的需求(如同一技能的不同连段表现不同)。
逻辑层面上,定义核心组件类SkillBrainBase,它是技能系统控制层级的最上层,由技能所有者持有(如PlayerController)。PlayerController可以通过SkillBrainBase播放指定索引的技能。同时,SkillBrainBase中持有技能共享数据,以满足不同技能间的通信需求。
SkillBrainBase下级为SkillBehaviourBase,一个SkillBehaviourBase对应一个技能,持有一个SkillConfig。该类定义每个技能的各自行为,监听SkillClip中的自定义事件,以及决定播放哪一个SkillClip,对技能进行状态管理。每个技能行为类都可以重写SkillBehaviourBase中的虚方法,以达到定制化的技能逻辑行为。另外,SkillBehaviourBase可以在SkillClip所有事件发生前后做特殊化处理,可以拦截事件的发生(如变身后技能音效改变、致盲后攻击判定无效),也就是对配置数据进行二次加工来完成特殊逻辑。
最后是SkillPlayer类,该类为运行时的技能播放终端,SkillBehaviourBase决定播放自己持有的SkillConfig中的哪个SkillClip后,将该SkillClip传递给SkillPlayer,SkillPlayer在运行时执行TickSkill()方法,对SkillClip中的数据进行逐帧播放,并将SkillClip中的事件向上传递给SkillBehaviorBase。另外,SkillPlayer也是武器切换功能的终端,其提供CreateWeaponOnWeaponPoint()给外部调用,以将不同武器物体生成在角色的武器握持位置。
SkillWeapon类是该技能框架下的武器组件类,挂载在各个武器物体上。该类持有武器物体上的碰撞体触发器,公开方法StartDetection()与StopDetection()来控制触发器的开启与关闭。当SkillClip中的技能判定检测数据的检测类型为武器类型检查时(除武器类型检查外,检测类型还有几种几何体形状类型),会通过SkillWeapon控制武器的判定检测。
技能运行时框架中的技能控制层级为PlayerController – SkillBrainBase – SkillBehaviour – SkillClip。