一个基于Unity制作的第三人称ACT框架
致力于创建一个配置简单、响应灵活的高速动作游戏:
做这个框架期间,我花精力最多、推翻重写次数最多的,就是角色的动作底层架构。
其实让角色动起来很简单:写个脚本读取摇杆输入,再写个脚本监听按键放技能就行了。但我很快就撞上了南墙——当“移动系统”和“技能系统”同时运行,它们就会在底层疯狂抢夺角色的控制权,导致游戏里出现各种诡异的“滑步”、“指令被吞”或者“角色抽搐”。
为了把这些幽灵一样的 Bug 彻底杀干净,并且让未来的开发不再痛苦,我从零开始搭建了现在的这套动作管线。具体来说,我解决了以下几个核心问题:
痛点: 以前的架构里,负责跑动的脚本(小脑)和负责打斗的脚本(大脑)是平级的。它们只能互相“猜”对方在干什么,经常因为 Unity 底层执行顺序的微小差异,导致一帧的误判。
我的解法: 我引入了一个明确的 ActionStateManager 作为唯一的“中央仲裁者”。我把它想象成一个红绿灯系统:
痛点: 随着游戏推进,角色的移动方式越来越多。不仅有普通的走和跑,还有“按住闪避键的疾奔”、“收刀状态下的慢走”等等。如果全写在代码里,就是无数个 if-else,最后连我自己都不敢改。
我的解法: 我把“移动表现”剥离了出来,做成了可以在资源目录里右键创建的数据文件(ScriptableObject)。 每个文件里只存三样东西:准入条件(比如“当前是否收刀”)、对应的动画资源,以及速度倍率。
收益: 底层的移动脚本现在变成了一个“无情的播放机器”。以后策划如果想加一个“残血瘸腿走”的状态,完全不需要我写一行代码。策划自己建一个数据文件,配上残血条件和瘸腿动画,丢进列表里就直接生效了。这种极度解耦的设计,大大释放了团队的生产力。
痛点: 在动作游戏里,从“攻击状态”切回“移动状态”的那个瞬间,引擎往往会因为状态机的计算延迟,播放出 1 帧的“默认站立动作”,这在玩家眼里就是极其难受的视觉抽搐。
我的解法: 我放弃了传统的 Animator 连线,接入了 Animancer 这种基于代码的代码驱动动画库。在控制权交接的同一行代码、同一个生命周期内,系统会瞬间算出下一个该播的移动动画,并直接执行带有时间的平滑过渡(CrossFade)。
收益: 实现了真正意义上的“零帧延迟”。动作之间的衔接如丝般顺滑,保证了硬核动作游戏必须具备的极佳操作手感。
痛点: ACT 游戏里经常有“招式后摇可以通过移动或闪避打断”的设计。如果用代码硬写时间(比如 if(time > 0.5f) 可以打断),调试起来简直是地狱。
我的解法: 我结合 Unity 的 Timeline,做了一套标签(Tag)系统。我在 Timeline 上拉一个自定义的色块轨道,色块覆盖的区域代表“禁止移动”。
收益: 策划只需要在图形化界面里,看着角色的动作,把那个色块稍微拖短一点,一个完美的“收招打断窗口”就做好了。底层系统每帧去读这个色块,色块一结束,立刻允许移动系统接管。这把极度复杂的底层逻辑,变成了直观的“涂色游戏”。
最后总结: 这套架构可能不是最炫技的,但它是我踩了无数坑之后,找到的最务实、最清晰的解法。“单线逻辑、显性状态、数据驱动”,这三个原则让我彻底摆脱了修 Bug 的泥潭,把精力真正还给了游戏玩法本身。
评论区
共 条评论热门最新