Chancy game dev notes · 全栈工程师

手感不是"最后再抛光"的那一层

把"打击感"拆开看:它是一堆有具体参数的功能。9 点偏移采样、0.2 像素阈值、渲染位置与物理位置之间的 20 毫秒。

· 6 分钟读完

#game-feel #realtime

"打击感"这个词我最不舒服的地方在于它听起来像玄学,而且被放在流程的最后一步 —— 逻辑做完了,"再来点 juice"。

Anuradhi Karunaratne 在 Game Feel: A Systematic Review 里把这件事正面顶了回来:那份综述的核心主张是 game feel 本身就是一项功能,应该在需求阶段就被要求、在实现阶段就被测试,而且需要专门投入的时间量级是"数百小时"。这不是修辞,是排期结论。

我接受这个说法,因为我自己的经验里,手感问题从来不是"特效不够",而是某个具体机制缺失。下面这些就是那些机制,以及它们可以精确到什么程度。

屏幕震动:先别抖摄像机

Vlambeer 的演讲《The Art of Screenshake》(Jan Willem Nijman,独立游戏开发者峰会 2014)里我认为最有工程含量的一条是:抖动应该作用于单个物体的偏移,而不是整个摄像机。原因是"清晰性优先" —— 摄像机一抖,玩家的准星、敌人轮廓、可交互提示全部跟着糊掉,而这些恰恰是玩家判定下一步操作的信息来源。(这场演讲我没有附链接:网上能找到的转载版本 ID 不一致,我无法确认哪一个才是原始上传,宁可只给标题。)

Karunaratne 那份综述里把射击震动拆成了可调参数,读完我印象最深的是那几个数字(文中给的是"常用起点",不是最优值):

参数他的经验值
最大振幅2~4 像素,按武器伤害缩放
频率15~30Hz(15Hz 用于大武器)
衰减200~300ms 指数衰减
触发前提只在真命中时触发,"没有 hit 就不要 shake"

最后那条很值得单独抄一遍:震动是反馈,不是氛围。空挥也抖,玩家很快就会把震动当成噪声过滤掉,于是它作为一个信息通道就报废了。

静止的摄像机是假的摄像机

这条是我从 Kyle Pittman 的 Smooth Camera Shakes & Screenshots 里捡到的:一个完全静止的摄像机在 CRT 时代会显得非常假 —— 因为那个年代大多数游戏用 15Hz 渲染,摄像机每 4 帧才更新一次,本身就在微微颤动。

Pittman 因此建议加一个幅度小到"意识不到是抖动"的常驻噪声(文中举的例子是 1 像素)。这里有个反直觉的量化结论:那篇文章给的数据是,人眼能察觉的屏幕运动小到 0.2 像素 —— 所以"我把它设成 1 像素玩家肯定看不出来"这种判断是靠不住的。

同一篇文章里还有个我认为可以直接抄进渲染代码的技巧:给每个物体一个 3×3 的九点偏移网格,逐帧随机挑一个点作为采样位置去贴图。因为浮点亚像素采样在多数引擎里开销高,而这种"离散抖动"在 2D tile 上几乎免费,视觉上却接近连续偏移。

顺便,同一个噪声源不要同时喂给摄像机和物体,否则相对位移被抵消,震动看起来像没生效 —— 这条我踩过。

真正的隐藏坑:你打中的是哪一帧的位置

Michael Lutz 的 The Hidden Pitfalls Of Game Interpolation 讲了一件非常具体的事,而且给了一段我很喜欢的观察:

在快节奏射击里,玩家从看到目标到按下扳机大约 200ms,而鼠标瞄准的精度比键盘方向控制高一个数量级 —— 于是插值带来的位置偏差在这个精度下变得可见。

后果很直接:如果碰撞检测跑在物理位置上、渲染跑在插值(过去)位置上,那么在快节奏游戏里命中测试应该用渲染位置;反过来说,用物理位置做判定,玩家"瞄着打"时会觉得手感莫名其妙。

文中给的工程参数是:提前渲染大约 20ms(1~2 帧),并且按"渲染延迟 + 一帧"的窗口去收集输入。还有两条约束我认为比参数更重要:

  1. 插值只取平均、绝不外推 —— 一旦外推到未来,误差会指数级放大,而且外推的轨迹和它下一帧要收敛到的真实轨迹在物理上不相容。
  2. 插值代码必须不持有权威状态:真实状态只由物理/网络写入,插值层只读,否则玩家位移会"漂"。

顺带一条很实用的:如果对象会按事件顺序反复重置插值目标(典型场景是弹跳),用 Vector2.Reflect 而不是 Vector2.SmoothDamp —— 后者会把角度变化抹成位置偏移,弹墙的样子就错了。

音画不是两件事

最后一条来自 Nijman:那篇演讲把音效称为"手感的 50%",并指出音画绑定有窗口 —— 两个声音之间间隔超过约 120~130ms 就会失去关联,玩家开始听到"哒-哒"而不是一个动作。配套建议是给音效配和动画同样的缓动曲线。

这条对我影响很大,因为它意味着"音频是另一个人另一步的活儿"这种分工本身就是 bug 来源。Sivitor 那篇 Juicing Gameplay With Audio 给了一个具体的耦合手段:枪声的低音强度跟随射击时的屏幕震动强度 —— 也就是把两个反馈通道挂在同一个信号上,而不是各调各的。

流程上我会改什么

Karunaratne 引的是 Swink 的那套 Gameplay-First Design 循环,我觉得值得贴在墙上:

  1. 先定义动作的"角色"(这个技能在体验上应该是什么感觉),
  2. 忽略美术和音效,只做无渲染的原型去验证它 —— Swink 的说法是"用纯粹的数学和力",
  3. 最后才做映射:把已经成立的手感翻译成视觉和听觉。

顺序反过来的话,你会用美术去掩盖机制的问题,然后就再也找不到它了。

一个例外我认可:如果某条反馈在输入产生的那一刻就已经可见(比如拖拽时目标立刻高亮),那它可以先于机制存在。Karunaratne 用了一个挺妙的类比 —— 这类东西像"进化上更古老的脑区",它不依赖机制正确就能生效。

参考来源