《Defold游戏开发入门》3.2 物理、碰撞与动画进阶

深入理解 Defold 物理对象、碰撞响应、动画状态和角色控制,设计稳定且具有手感的运动系统。

3.2 物理、碰撞与动画进阶

玩家不会看到你的碰撞掩码或速度向量,却会立刻感觉到角色是否笨重、是否被墙角卡住、跳跃是否可信。物理、碰撞和动画是三套不同系统,只有把边界和顺序设计好,它们才会共同制造“手感”。本章以横版角色为例,说明如何选择物理模型、处理接触信息、组织动画,并建立可调试的控制器。

先决定运动模型

物理引擎擅长解决刚体、力、摩擦和反弹;它不一定适合每一种角色移动。推箱子、弹球、车辆、可滚落物体非常适合动态刚体;平台跳跃主角则往往需要更可控的运动,因为设计者希望精确规定加速度、空中转向、跳跃高度和贴墙行为。不要为了“使用物理”而让每个对象都成为动态刚体。先列出体验目标,再选择静态地形、动态道具、触发器和角色控制的组合。

静态碰撞对象适合地面、墙和不移动的几何体,成本低且稳定。动态对象由物理世界模拟,受质量、摩擦、恢复系数、阻尼和力影响;移动它们时应使用合适的物理 API,而不是每帧强行改坐标。触发器只报告相交,不承担实体阻挡,适合拾取范围、终点、伤害区和检查点。把视觉精灵、碰撞形状和规则脚本放在同一游戏对象或一组明确关联的对象中,能使调试时更容易找到责任位置。

碰撞分组是规则设计

碰撞分组和 mask 不是最后的性能选项,而是“哪些事物可以发生关系”的规则表。可以定义 playerenemyplayer_bulletenemy_bulletworldpickupsensor 等类别,再规定每类与哪些类别交互。玩家与世界、敌人、拾取物相交;玩家子弹与世界和敌人相交;敌人子弹不应击中敌人本身。这样不仅降低无用检测,也让行为意图可读。

为组名建立项目级约定,避免不同关卡写出 monstersenemyfoe 三个近义词。碰撞消息到达后仍要检查对象状态:已死亡的敌人不应再次掉落奖励,处于无敌期的玩家不应重复扣血。碰撞是“可能发生交互”的信号,不是无需验证的最终裁决。

接触信息与地面判定

角色控制的常见难点是判断“是否站在地面”。最脆弱的做法是碰到任何对象就设为 grounded,离开就取消;角色同时接触墙、斜坡或多个图块时,这种布尔值很快出错。更可靠的做法是依据接触法线判断接触方向:法线大致朝上才表示脚下有支撑,朝侧面表示撞墙。每个物理步开始前先清空本帧接触信息,再由碰撞消息收集,最后计算状态,避免旧接触永久残留。

地面判定还需要宽容设计。短暂离开边缘的一帧不应立刻让玩家失去跳跃机会;可以设置很短的“土狼时间”,在离地后仍允许跳跃。按键稍早到达时可以设置输入缓冲,等角色落地的短窗口内自动起跳。这些机制不是掩盖 bug,而是把人类输入的不精确转化为稳定体验。所有宽容窗口都应有明确常量并在测试中调整。

速度、加速度与跳跃曲线

角色移动不应只写成“按键就设置固定速度”。地面加速、减速、空中控制、最大速度、重力和终端下落速度共同决定手感。把它们放入配置表,通过小步调参而不是反复改散落的数字。水平速度可朝目标速度逐渐逼近;松开按键后用不同的减速度;跳跃则在起跳瞬间给予向上速度,随后持续受重力影响。限制下落速度可以避免数值过大,也有利于碰撞稳定。

跳跃高度与时间应从体验目标反推。先决定角色应在多久到达最高点、应能跨越多宽的坑,再用测试场景观察轨迹。变量跳跃可在玩家松开按钮后增加下落或削减上升速度;二段跳、冲刺、墙跳则是状态机上的额外转移,而不是在每个 if 里加一个布尔开关。每增加一种运动,写出它与受伤、暂停、地面、空中之间的优先级。

动画是状态的可见结果

动画不应反过来决定物理。角色的规则状态如 grounded、vertical_velocity、facing、is_hurt 经过映射后选择 idle、run、jump_up、fall、hurt 等动画。这样即使换掉整套美术,控制器仍然正确;同样,即使动画因资源加载延迟或被关闭,碰撞与移动也不受影响。切换时只在动画名发生变化时调用播放函数,避免每帧重启动画。

动画事件也应谨慎使用。攻击命中可以在明确帧附近打开判定窗口,但最终伤害仍由规则系统验证目标、阵营和冷却。脚步声可以跟随动画节奏,却要根据角色是否真的在地面和是否可听来决定播放。把“表现时机”与“游戏事实”分开,能避免网络、暂停或帧率变化导致不同步。

处理常见边界问题

墙角卡住通常来自碰撞形状过于贴近美术、地面与墙的图块间有缝、或水平和垂直运动顺序不当。先开启碰撞形状可视化或制作简化场景,逐项排查。穿透通常来自速度过高、形状过薄、直接改坐标绕过物理或时间步过大;不要首先把碰撞体无限加厚。角色抖动可能是父子变换、物理位置和视觉插值同时修改造成的,需要确保只有一个系统拥有最终位置。

移动平台是综合测试。平台本身可能是运动学或脚本驱动对象,角色站在其上时需要继承适当位移,同时不能因碰撞消息顺序而被反复弹开。先在单个平台、单角色、无敌人的集合里完成它,再带入关卡。斜坡、单向平台和传送带也应单独验证,因为它们会暴露普通地面测试看不出的接触问题。

调试场景与调参记录

为角色控制建立专用测试关卡,包含不同高度平台、窄缝、墙角、移动平台、伤害区和长距离跑道。屏幕上显示当前状态、速度、接触法线、剩余土狼时间和输入缓冲,或至少在 Console 中按需记录。每次调参只改一到两个值,并让多个试玩者在同一场景中尝试。开发者熟悉关卡后会无意识弥补控制缺陷,外部玩家的失败位置更有诊断价值。

本章练习是完成一个可调的横版控制器:地面加速与空中控制不同,按键支持缓冲,离开边缘支持短暂土狼时间,碰到敌人后进入短暂无敌,动画正确区分待机、跑步、上升和下落。给所有关键参数注释单位和体验目的。做到这一点后,物理不再是偶然凑出的效果,而成为可持续打磨的系统。

角色控制器的职责边界

一个可维护的控制器可以拆为四个小层。输入层记录玩家意图;运动层根据状态和参数计算目标速度;碰撞层收集接触、执行物理移动并报告结果;表现层依据最终状态选择动画、朝向和音效。它们可以暂时写在同一个脚本里,但应保持函数边界。这样改成 AI 控制、回放控制或触屏控制时,只需替换输入意图;替换角色皮肤时,只需改表现映射;调整手感时,集中改运动参数。

不要把碰撞回调直接写成完整的规则流程。回调的任务是记录“与谁、以什么方向、何时接触”,随后由控制器在合适阶段消费这些信息。原因是一个物理步里可能收到多个接触,顺序也不应作为玩法依据。先聚合,再决策,能避免墙壁碰撞偶然覆盖地面状态,也能让你清楚处理“同时踩到终点和伤害区”的优先级。

形状、单位与镜头的协调

角色精灵的原点、碰撞体中心、脚底位置和镜头跟随点应被明确标注。很多动画抖动不是动画帧问题,而是不同帧的图像锚点不一致,或脚本以精灵中心而物理以脚底为基准移动。可以在编辑器中为所有角色统一约定“局部原点在脚底中心”,让图像导出、碰撞形状和生成位置都遵循这一点。命中框、受击框和交互范围需要时可拆成独立传感器,而非强迫一个形状承担所有职责。

所有参数都要有单位:速度是世界单位/秒,加速度是世界单位/秒²,土狼时间是秒,形状尺寸是世界单位。给参数取 jump_speedgravitymax_fall_speed 等名称,并记录它服务的体验。只有单位清楚,才能在设计分辨率、镜头缩放或角色尺寸变化时系统地调整,而不必靠盲目乘以一个系数。

处理受击、击退与无敌

受击是物理与规则相交的典型场景。碰撞检测只发现接触;伤害系统判断攻击方、冷却和无敌;控制器切入 hurt 状态,施加击退,设置无敌结束时刻;表现层闪烁并播放音效。击退方向通常依据攻击来源到角色的位置,而不是仅依据精灵朝向。无敌期应明确是否仍阻挡身体、是否仍播放命中效果、是否允许拾取物触发。

给无敌状态设置视觉和调试指示。没有可见提示时,玩家会认为后续碰撞失效;没有日志时,开发者会误以为伤害系统漏算。对连续接触的敌人,要验证无敌结束的一帧不会因为仍在重叠而连扣多次,必要时加入离开接触或冷却规则。真正稳定的受击系统来自这些边界测试,而不是只在单次碰撞中看起来正确。

动画混合与事件一致性

当动画数量增加,先建立一张状态到动画的映射表,再决定哪些转场需要过渡。奔跑到跳跃可立即切换,受伤到死亡可能需要强制优先,落地可短暂播放落地动画再回待机。不要让多个系统同时播放同一 sprite;由表现层拥有最终播放权,其他系统只发送状态或事件。若需要镜像,统一在表现层根据 facing 调整,避免物理形状也被意外翻转。

用慢动作、低帧率和极端输入测试动画事件。攻击命中帧、脚步声、落地尘土等表现事件可能在切换或暂停时被跳过或重复。将规则命中与动画事件分开,并在必要时记录已触发标记,才能保证游戏事实不依赖某一帧恰好被渲染。

验收一套运动系统

运动系统的验收不能只看“能走能跳”。列出可重复操作:从平台边缘走下后在宽容窗口内按跳跃;在窗口外按跳跃应失败;左右快速交替时速度不超过上限;落地后立刻起跳不会被旧下落速度拉回;贴墙、斜坡和移动平台上动画不抖;暂停、恢复和重开后所有临时状态被清空。将这些操作录成短视频或自动化输入序列,未来调参后就能快速发现手感回归。

也要测量最差条件:大量动态对象、低帧率、触摸连按和长时间运行。物理稳定性不是只在理想 60 帧下成立。若某种玩法只在帧率很高时可靠,应先改正时间步、碰撞或状态逻辑,而不是要求玩家使用更快设备。稳定的基础会给后续敌人、道具与关卡设计留下真正的空间。

从参数到手感的迭代

调参时同时保留主观与客观记录。主观记录包括“起跳是否果断”“空中是否可控”“受击后是否明白原因”;客观记录包括跳跃最高点、跨越距离、达到最大速度所需时间、伤害后的无敌秒数。让同一组试玩者在改动前后比较,而不是只凭开发者当天的感觉。若两项参数总是一起修改,就无法知道哪个真正改善了体验。

为角色建立一页参数说明,写下每个值的默认、可取范围和修改理由。以后添加加速道具、不同地面、装备或敌人击退时,这张说明能防止系统变成一堆互相抵消的魔法数字。运动设计可以很精细,但精细不等于复杂;少量相互协调、可测量的参数往往比大量特例更有表现力。

在项目迭代中定期回到基础测试关卡。新动画、新碰撞形状或镜头缩放都可能悄悄改变原有手感;只有使用同一组跳跃、落地和受击测试,才能判断变化来自新内容还是控制器回归。

与关卡设计共同验证

控制器参数不能脱离关卡测试。跳跃高度决定平台垂直间距,水平速度决定镜头前置和敌人预警距离,碰撞体宽度决定通道最小尺寸。关卡设计者应使用明确的单位和辅助标记,而不是凭视觉估计“应该跳得过去”。当设计想制造高难度挑战时,先确认失败来自玩家可理解的决策,而不是碰撞形状、镜头遮挡或输入缓冲的偶然。

也要测试角色与可交互对象的组合:拾取物在跳跃顶点能否可靠触发,移动平台上的敌人是否给出正确击退,传送门和检查点是否在高速移动时漏检。将这些组合写入回归清单,能避免每新增一种关卡元素就破坏既有运动规则。

最后,让表现帮助而不是干扰控制。落地尘土应落在真实脚底,朝向翻转应与攻击方向一致,受击闪烁不应掩盖无敌结束时机。物理、动画和音效指向同一事实时,玩家即使不知道内部规则,也会自然建立正确预期。

若遇到难以解释的接触问题,先把角色、地形和传感器替换为颜色不同的简单形状,关闭动画和特效后复现。将复杂表现逐项加回,比在完整关卡中猜测碰撞回调顺序更快、更可靠。

对每个修复过的物理 bug 保留一个小测试区域。它既是回归用例,也能让新人理解当初为何选择某个宽容窗口、形状尺寸或碰撞分组,而不会在后续优化中无意删除必要规则。

随着关卡数量增长,这些测试区域还能成为统一的角色手感基准,避免不同关卡各自引入不兼容的运动假设。

将测试场景与参数说明一起维护,才不会在角色美术或关卡规模改变后丢失原先稳定的控制基线。

稳定的基线是大胆尝试新玩法的前提。

因此应始终优先保护基础控制。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「defold」更多文章