帧率与输入系统设计
导言
战斗策划不需要会写输入系统,但写设计文档时写的”目押 8 帧”、“前摇 20 帧”、“顿帧 5 帧”——这些数字的底层依据是什么、不同帧率下还成立吗、多人共斗时该怎么调——这篇文章是我自己对这些问题的整理。
在游玩即时制的动作类游戏时,玩家在战斗中常遇到几种体验:
- “这BOSS出招好快,根本来不及反应”——BOSS的前摇时长太短,难以反应或预判行为
- “我明明按了,为什么没反应?“——按键没有被系统正确读到,或者读到了但角色当时不能执行,输入直接丢了。
- “从按下按键到角色行动,中间好像慢了半拍。“——输入被读到了,但响应有明显的延迟感。
想要解决这些问题,我们需要先了解人类在游玩游戏并作出反应所经历的大致过程。从玩家看到怪物出招到角色做出反应,中间经过的链路大致是这样的:
flowchart LR
A["看到怪物抬手"]
B["大脑判断
'该闪避了'"]
C["手指按下按键"]
D["游戏读到输入"]
E["逻辑帧处理"]
F["角色播放
闪避动画"]
A --> B --> C --> D --> E --> F
这整个链路加起来才是玩家感受到的”反应时间”。其中最基础的限制在开头——人从看到视觉信号到做出按键动作,本身就需要大约 200-250ms(视觉简单反应时)。除此之外,完整时间里还会继续被几项不太显眼的时间成本消耗:
- 显示器刷新延迟:60Hz 屏幕每 16.7ms 才刷新一次画面。即使游戏已经算好了下一帧,你也得等屏幕刷新才能看到——最多多等 16.7ms,意味着玩家在看到怪物抬手的前摇前就浪费了16.7ms。
- 引擎输入处理延迟:游戏每帧处理一次输入。如果你按键刚好落在两次处理之间,这个输入就要等到下一帧才被读到——又是最多 16.7ms。
- 其他系统开销:操作系统调度、USB 控制器轮询、音频处理等附加开销。
一笔一笔加起来,即使前摇在设计中有 20 帧,名义上给了玩家 333ms 反应,但玩家实际能用来反应的时间可能只有 250ms 甚至更少。
后文会按这些环节继续拆解。
1. 人类的反应时——所有帧数窗口的硬约束
所有帧数窗口设计的底层依据,都是人类的生理反应极限。比人类能反应过来的时间还短的窗口,本质上就是要玩家靠预判来完成的——设计者需要清楚这个前提。
1.1 视觉简单反应时——一个正常人看到东西到按下按键需要多久
一个正常年轻人在最理想条件下的视觉简单反应时大约是 200-250ms。这个范围来自 Woods 等人(2015)的大规模研究——他们在 1469 名 18-65 岁受试者中测量了视觉简单反应时:受试者注视屏幕中央的十字,高对比度的靶心图随机出现在左侧或右侧视野,看到后用食指尽快按下鼠标按键。实验使用了高精度游戏鼠标(Razer Sidewinder,1kHz USB 轮询率),并对硬件延迟做了单独标定——显示器延迟约 11ms、鼠标按键延迟约 6.8ms,总计约 18ms。
测得的一般人群平均简单反应时为 231ms,扣除硬件延迟后约为 213ms。其中 18-24 岁最年轻组的平均反应时为 218ms(校正后约 200ms)。反应时会随年龄缓慢增长(约 0.55ms/年),性别和教育程度的影响很小。
也就是说,一个正常年轻人在最理想条件下的视觉简单反应时大致落在 200-250ms 区间——下限对应 Woods 研究中年轻受试者校正后的结果,上限对应包含各年龄段的一般人群均值。
作为对比,Bragança 等人(2021)在视光学生中做了一组对照实验。45 名 18-24 岁的受试者根据过去三个月每周玩动作游戏的时长分为三组(每组 15 人):游戏玩家(>5 小时)、半玩家(1-5 小时)和非玩家(几乎不玩)。实验用一部 60Hz 屏幕的 Android 手机(Xiaomi Redmi 5)安装了两个 app——反应时测试 app(Banensoft)和反应训练器 app(Jilder.com)——来测量简单视觉反应时:手机屏幕从红色变为绿色时尽快点击屏幕,每个受试者测两次取平均。基线测量后,受试者被要求每天至少练习两次,持续一周,然后重复测量。
| 受试人群 | 测试内容 | 练习前 | 练习后 | 来源 |
|---|---|---|---|---|
| 游戏玩家(>5 小时/周) | 手机 app 视觉反应时测试 | ~251ms | ~241ms | Bragança et al., OEPF 2021 |
| 半玩家(1-5 小时/周) | 同上 | ~301ms | ~265ms | Bragança et al.(同篇对照) |
| 非玩家 | 同上 | ~293ms | ~269ms | Bragança et al.(同篇对照) |
基线时游戏玩家(~251ms)比非玩家(~293ms)快了约 40ms。经过一周在相同 app 上的每日练习后,三组反应时都有下降,半玩家和非玩家的提升幅度更大(30-40ms),游戏玩家的提升较小(约 10ms),差距缩小。练习可以缩短反应时,但幅度有限。
需要说明的是:Woods 的数据来自实验室高精度设备(gaming mouse + 硬件延迟标定,n=1469),测得的一般人群均值(~231ms)低于 Bragança 的非玩家组(~293ms),这主要是因为手机 app 的计时精度和实验室设备有差距,不宜直接跨研究对比。
到了电竞选手层面,简单反应时的差异进一步缩小。这里可参考两组不同实验。
第一组是 Bickmann 等人(2021)的实验。他们用 Vienna Test System(标准化的心理运动测试系统)测量职业和非职业电竞选手的简单视觉反应时,任务是在看到灯光信号后尽快按键。
| 受试人群 | 测试内容 | 反应时(均值) | 来源 |
|---|---|---|---|
| 职业电竞选手(18 人) | Vienna Test System 简单视觉反应时 | ~249ms | Bickmann et al., 2021 |
| 非职业高水平玩家(21 人) | 同上 | ~252ms | Bickmann et al.(同篇对照) |
| 传统运动员(36 人) | 同上 | ~257ms | Bickmann et al.(同篇对照) |
第二组是 Luu 等人(2021)的实验。他们用了颜色线索测试(color cue test)和尺子下落测试(ruler drop test)来比较电竞选手、传统运动员和非运动员对照组的反应时。
| 受试人群 | 测试内容 | 反应时(均值) | 来源 |
|---|---|---|---|
| 电竞选手(12 人,FPS 为主) | 颜色线索 + 尺子下落测试 | ~269ms | Luu et al., 2021 |
| 大学橄榄球运动员(12 人) | 同上 | ~276ms | Luu et al.(同篇对照) |
| 非运动员对照组(12 人) | 同上 | ~305ms | Luu et al.(同篇对照) |
职业电竞选手和非职业高水平玩家之间的差异不到 10ms,且无统计显著性;在 Luu 的实验里,电竞选手虽然快于非运动员对照组,但和传统运动员之间的差距也不大。这意味着从普通玩家到职业选手,简单视觉反应时的提升空间非常有限(通常也就是几十毫秒量级)。职业选手的真正优势可能更多体现在游戏内的决策速度、模式识别和情境预判,而不是单纯的按键反应上。
把 1.1 这一节里的几组实验合在一起看,真正可以落下来的结论其实不复杂:普通人的简单视觉反应时基线大致就在 200-250ms 这一档;游戏经验和短期练习确实能把这个数字压缩一点,但幅度通常只有几十毫秒;到了高水平玩家或职业选手阶段,单纯拼“看到信号后按得更快”已经不是主要差异,真正拉开体验和水平的,更多是识别、经验和预判。
了解了简单反应时这个概念之后,我们还需要想办法把它换算成动作游戏中更常用的时间单位——帧数,然后看看不同长度的窗口在动作游戏中实际对应什么手感。
1.2 各帧数窗口对应什么手感——格斗游戏社区几十年的实测积累
格斗游戏社区(FGC)用了几十年来测试”几帧的窗口到底有多难”。Celia Wagar (2016) 和 Wavu Wiki 的框架是目前最广泛引用的参考。
以 60fps(1 帧 ≈ 16.67ms) 为标准:
| 帧数 | 时长 | 实际体验 |
|---|---|---|
| 1 帧 | 16.7ms | 格斗游戏最严苛的窗口。人类无法稳定靠反应完成,依赖预判和肌肉记忆。代表:Super Turbo 的受击反转窗口(Celia Wagar, 2016) |
| 2 帧 | 33.3ms | 《街霸 3》的 Parry 窗口、《大乱斗》的 Power Shield。极少数高玩可以练到稳定,但对一般玩家来说和 1 帧没区别 |
| 3 帧 | 50ms | 《街霸 V》的最小连段目押窗口。普通玩家通过一段时间的练习可以稳定复现 |
| 7-8 帧 | 117-133ms | 格斗游戏 Just Frame 的”甜区”——街霸 3 的格挡、大乱斗的 L-Cancel。可以练到稳定,但需要刻意练习。这个区间也是我 Demo 里目押 8 帧的参照来源 |
| 15-16 帧 | 250-267ms | 一般人群的平均简单反应时。窗口长于这个值,正常人都能稳定反应(KI Infil Guide; Wavu Wiki) |
| 20 帧+ | 333ms+ | 多数玩家可以稳定反应。Wavu Wiki 对《铁拳 7》的标定:i20+ “borderline reactable 10-70%”, i23+ “reactable 20-90%”, i26+ “easily reactable 40-99%“ |
| 30 帧(0.5s) | 500ms | 极其宽松。这个长度下”反应”已经不是瓶颈,“要不要反应”才是玩家的决策 |
1.3 输入延迟会压缩理论上的反应窗口
先把输入延迟拆开。为了和后文的展开顺序对齐,本文把它分成四层:
- 逻辑与帧率延迟(第 2 章讨论)——逻辑帧和渲染帧怎么跑、怎么对齐、前摇怎么换算,这些都会影响“按下去以后多久能看到结果”。
- 输入系统延迟(第 3 章讨论)——游戏什么时候读输入、怎么记录输入、读到了但暂时不能执行时怎么处理。
- 设备与平台延迟(第 4 章讨论)——控制器/触屏的采样和传输、OS 调度、驱动队列、显示链路。这部分是硬件和系统带来的额外时间成本,游戏本身改不了。
- 网络延迟——只影响联机模式,不在本文范围内。
这一节先看最前面的那部分消耗:设备和平台本身会先占用多少时间。
FGC 实测数据(UMGamer / WydD, 2021):
| 环境 | 输入延迟 | 等效消耗帧数 |
|---|---|---|
| 街机 Cabinet | ~1-2 帧 | 占用 1-2 帧 |
| PC 60Hz 显示器 | ~3-4 帧(~50-67ms) | 占用 3-4 帧 |
| PC 120Hz 显示器 | ~2 帧(~37ms) | 占用 2 帧 |
| PS4《铁拳 7》 | ~4.4 帧(~74ms) | 占用 ~4.5 帧 |
| 移动端(30fps + 触屏) | ~5-8 帧(~100-167ms) | 最多占用 ~8 帧 |
拿 20 帧前摇的 Boss 招式来说,决定玩家能不能“看见再反应”的,不只是总时长,还要看明确信号到底给得早还是给得晚。提示如果一直拖到动作后段才出现,纸面上的 20 帧窗口看着不短,玩家真正拿到手的反应时间可能已经不够了。
同样的 Boss 放到移动端,触屏输入延迟会更高。移动端能做的也不是直接降低这段物理延迟,而是用帧率设计和输入系统去消化它。这部分第 4 章还会展开。
2. 逻辑帧和渲染帧——游戏在跑两套时钟
对于动作游戏来说,游戏在跑两套时钟。
2.1 两套时钟
| 逻辑帧(Logic / Physics Tick) | 渲染帧(Render FPS, Frame) | |
|---|---|---|
| 做什么 | 算 AI 决策、碰撞判定、动画采样、输入处理 | 把算好的结果画到屏幕上 |
| 速度 | 固定——比如每 16.67ms 跑一次(60Hz) | 不固定——取决于设备性能和场景复杂度 |
| 谁决定这个速度 | 项目设置里写死的 Fixed Timestep | GPU 能跑多快就跑多快 |
| 两者关系 | 独立运行,不随渲染帧率变化 | 每次渲染帧开始前,拿最新的逻辑结果来画 |
逻辑帧和渲染帧分离的好处是:渲染帧率可以掉到 30fps 甚至更低,但只要逻辑帧稳定在 60Hz,所有判定、窗口、AI 行为都不会受影响。
在不同渲染帧率下,实际的表现不同:
- 30fps 渲染时,一个渲染帧内可能累积了 2 步逻辑结果。引擎会先把两步逻辑都算完,然后用最新的结果来画这一帧。操作手感仍然是 60fps 的,只是画面看起来没那么流畅。
- 60fps 渲染时,渲染帧和逻辑帧基本上是 1:1 对应。这是动作游戏最理想的状态。
- 90/120fps 渲染时,渲染帧的刷新速度超过了逻辑帧。有些帧里逻辑没有新结果可以画,引擎就用上一帧的结果来渲染,或者用插值来补中间状态。
2.2 “改帧数”到底在改什么
当有人说”把游戏从 30fps 改到 60fps”时,这句话有两种完全不同的意思:
| 只改渲染帧率(最常见的情况) | 改逻辑帧率(大工程) | |
|---|---|---|
| 实际做了什么 | 解锁帧率上限,让 GPU 放手跑 | 把逻辑时钟从 33ms/步 改成 16.67ms/步 |
| 对玩法的影响 | 画面更流畅、输入延迟降低 | 时间刻度单位变了,所有帧数配置都要重新算 |
| 工作量 | 几乎为零 | 牵一发动全身——动画、判定表、物理参数全部要换算 |
《原神》PC 版解锁 60fps 属于前者——逻辑帧率没变,纯粹是渲染更流畅了。但如果一个原本为 30fps 设计的格斗游戏要逻辑升级到 60fps,那就属于后者——原本”15 帧的前摇”在 30fps 下是 0.5s,到了 60fps 如果不改成”30 帧”,这个前摇就变成了 0.25s,手感直接变了。
2.3 性能掉帧是怎么回事
当 GPU/CPU 性能不足的时候,渲染帧就会”掉帧”。更直观的看法不是谁调用了谁,而是:逻辑照常推进,但屏幕实际显示少了一帧。
对战斗手感的影响:掉帧期间玩家损失了数帧的可视信息。如果一个闪避提示恰好出现在被跳过的帧里,玩家就相当于少了几帧的反应时间。格斗游戏在优化时宁可降低画质也要锁定 60fps,原因就在这里。
至此已经介绍了输入链路中的两个主要瓶颈——人的反应时和系统帧率。但输入链路上还有两个问题没有解决:
- 游戏读到输入的频率是多少?(读多快)
- 读到了但角色不能执行时怎么办?(存多久)
这就要更进一步地拆解输入系统了。
3. 输入系统的三个概念——它们解决不同的问题
战斗策划设计的所有操作——目押、连段、蓄力、闪避、弹反——最终都要通过玩家的手指在控制器或触屏上执行。输入系统就是在处理一个问题:玩家的操作意图如何被游戏准确、及时地理解并响应。
这三个概念是战斗策划最常听到也是最容易搞混的,我之前也常常混淆这些概念。先说明它们之间的关系:
- 输入缓冲是一个总称——指”系统暂时存储玩家的按键输入,等可执行时再处理”的机制,它实质是一个缓冲池。
- 预输入是输入缓冲的一个使用场景——特指”玩家在当前动作(出招中/后摇)还没结束时提前输入下一个指令”的情况。
- 输入采样是另一个维度的问题——它不存任何东西,只管”游戏以多高的频率去读物理按键输入”。它和输入缓冲解决的不是同一个问题。
下面分别展开。
3.1 输入缓冲(总称)——“我明明按了,为什么没生效?”
输入缓冲的核心逻辑是:系统把玩家的按键记录保留一小段时间,等角色可执行时再处理。
flowchart LR
A["玩家按攻击键"] --> B["系统记录:攻击请求有效 5 帧"]
B --> C{"角色当前能否攻击?"}
C -->|能| D["立即执行"]
C -->|不能| E["帧计数器递减"]
E --> F{"减到 0?"}
F -->|否| G["等待下一帧,再检查角色状态"]
G --> C
F -->|是| H["丢弃"]
它对应三个不同层面的问题,也对应了”按了没反应”的三种常见原因:
① 角色当前不可执行 玩家按下按键时,角色还在收招/硬直/播放动画,不能接受新的指令。没有缓冲的话这个输入就会失效——玩家明明按对了时机,但系统不认。 → 典型的解决方案如图所示:按键记入缓冲,帧计数器递减,角色可执行时立即消耗。
② 按键时机与可执行时机不完全对齐 输入检测是离散的(假设每帧检测一次),但玩家的按键是连续的——可能在任意时刻按下并松开。如果一次按键恰好完全发生在两次检测的间隙里(比如一个很短的轻触),那系统就不会知道这次按键存在过。没有缓冲的话这个输入就永久丢失了。
| 时间 | 帧 N (检测点) | 帧 N ~ 帧 N+1 之间 (无检测) | 帧 N+1 (检测点) |
|---|---|---|---|
| 按键信号 | 无 | ⏎ 按下并松开(信号出现又消失) | 无 |
| 输入检测 | 读到 → 无按键 | ← 检测不到 → | 读到 → 无按键 |
| 有缓冲 | 系统捕获到信号变化,记入缓冲 | 读到缓冲中有未处理的输入 ✅ | |
| 无缓冲 | 系统捕获到信号变化,但没有记录 | 无记录,输入永久丢失 💀 |
数值演示(假设游戏跑 60fps,每 16.67ms 检测一次):
| 时间 | 0ms | 5ms | 8ms | 16.7ms |
|---|---|---|---|---|
| 事件 | 帧 N 检测点 → 无按键 | ⏎ 玩家按下受身键 | 玩家松开受身键 | 帧 N+1 检测点 → 无按键 |
| 无缓冲 | 无记录 | 无记录 | 无记录 | 无记录 → 永久丢失 |
| 有缓冲 | 无记录 | 捕获:按键信号从无→有 | 捕获:按键信号从有→无 | 读取缓冲:有一个未处理的按键事件 ✅ |
按键从按下到松开只持续了 3ms,远短于两次检测的间隔(16.67ms)。没有缓冲的话,这个输入完全消失在间隙里,系统永远不会知道它存在过。
比如:我之前做 Demo 的受身系统(受击后可脱离受击状态并进入闪避状态)时就遇到了这个问题。虽然受身窗口可以比较长,但如果没有输入缓冲,在这几帧之间的间隙按下的输入都可能被漏检,玩家体验就是”我按了但角色没反应”。
Unity 官方博客在讨论旧版输入系统(GetButtonDown 轮询方式)时明确指出了这个问题:“If the input is pressed and released faster than the framerate, it may never be seen.”(按键按下又松开的速度如果快于帧率,系统可能永远看不到这个输入。)——这也是现代输入系统(如 Unity 的 Input System 和 Godot 的新版输入)采用事件驱动 + 时间戳缓冲来替代帧轮询的原因之一。
缓冲在这里不是”存下来等窗口重开”——那是预输入的事。它做的是另一件更基础的事:把一段短暂的按键信号延长,保证它能活到下一次检测点。
③ 降低精度门槛 没有缓冲的闪避/弹反窗口如果只有 1-2 帧,玩家必须精确卡在那几帧内按键,这接近人类反应极限。缓冲把有效接受窗口拓宽了几倍,但没有增加判定窗口本身的长度——这就是”窗口较小但手感不紧”的关键。
典型例子:
- 受击硬直中按闪避——玩家被击中后处于硬直状态,连按闪避键。系统记录下按键,硬直一结束就执行闪避,不需要玩家精确卡在硬直解除的那一帧按。
- 跑动中提前按跳——角色在跑动动画中,玩家按了跳。跑动还剩 3 帧才能被跳跃打断,系统保留这个跳跃输入,3 帧后执行。
所以输入缓冲的核心原则就是给玩家留出余量,不必每次都把输入时机压到极限。
补充:不要把输入缓冲和 Coyote Time(土狼时间)搞混
它们底层机制不同:
- 输入缓冲:存的是”输入本身”。玩家按跳 → 系统记录”这里有一个跳跃请求,有效期 5 帧”→ 条件满足时执行。
- Coyote Time:改的是”条件判定”。玩家离开地面 → 系统把”是否在地面上”这个判断条件的返回值延迟关闭,多保持几帧为 true → 玩家看到”我已经掉出去了还能跳”。
简单说,一个在输入端宽容,一个在条件端宽容。两者解决类似的问题(给玩家的操作留余量),但实现路径完全不同。实际项目中经常同时使用。
3.2 预输入——输入缓冲的最常见使用场景
预输入不是一套独立的系统——它是输入缓冲在”玩家在当前动作还没结束时提前输入下一个指令”这一场景下(常见于连招系统内)的具体应用。
没有预输入的话,连段就变成了一个节奏游戏——必须精确地在上一招结束时的那一帧按下下一招。差一帧早了,按键被丢弃;差一帧晚了,连段断了。这不是设计者想要的”节奏感”,玩家的注意力从”打什么”被转移到了”什么时候按”。
典型例子:
- 《鬼泣》里但丁的叛逆之刃第三刀还没砍完时按第四刀——系统存输入。
- 格斗游戏里在后摇阶段输入必杀技指令(比如 236P),系统存下来,后摇结束自动执行。
同一机制下的两种场景对比——关键看”按下去时角色在干什么”与”缓冲时间”:
| 空闲/受击状态下的缓冲 | 动作中的预输入 | |
|---|---|---|
| 按下去的时机 | 角色处于空闲/受击/移动等非动作状态,但因为某些原因暂时不能执行该操作 | 角色正在执行一个动作(出招中),你在它还没结束时按了下一个动作 |
| 窗口长度 | 通常较短(3-8 帧 / 50-133ms)。因为角色很快就可行动了,缓冲只需覆盖”差几帧”的间隙 | 通常较长(5-20+ 帧 / 83-333ms+,取决于游戏类型)。因为当前动作还剩不少帧,需要给玩家足够的时间提前输入 |
| 存储方式 | 固定帧数有效期,递减直到过期或可执行 | 暂存队列,等当前动作结束后自动执行 |
| 目的 | 防止”差一点就按到了” | 让连段可以”先按再说” |
| 典型场景 | 受击硬直中按闪避、跑动中提前按跳 | 第一刀后摇中按第二刀、后摇中输入必杀技指令 |
两者底层通常是同一套机制(都是”把一次按键存一会儿”),区别主要在终止条件:空闲状态下的缓冲按固定帧数递减,到期未执行则丢弃;动作中的预输入一般不需要等到整个动画(含后摇)结束——通常攻击判定完成后一段时间内就会开放可取消窗口,预输入在这个窗口内触发执行。写设计文档时,只需说清楚”以时间还是以事件帧为终止条件”即可。
预输入窗口的长度没有统一标准,完全取决于游戏想要的手感取向:
- 硬核格斗游戏(街霸、GG):窗口 ~5-9 帧(80-150ms)。玩家必须主动练习才能稳定连段,不熟练时连段断掉是”玩家没掌握窗口”而非”系统不认”。这个长度和格斗游戏 Just Frame 的甜区一致。
- 主流 ACT/ARPG(鬼泣、战神):窗口 ~12-20 帧(200-333ms)。招与招之间明显放宽,玩家不需要精确卡帧就能接上连段,容错空间够大。
- 轻度/移动端 ACT:窗口可长达 ~30 帧(500ms)甚至”足够长——直到此动作后摇结束前”。典型表现就是”按得越快出得越快,按得慢也不丢段”,属于尽可能照顾所有操作水平的设定。
预输入太短和太长,问题并不一样:短了,连段门槛高,新手容易接不上;长了,玩家可能已经改主意了,系统却还是把刚才存下来的输入执行出去。预输入窗口本质上就是一个手感调优参数,取决于你希望玩家把输入时机控制到多准。
3.3 输入采样——“按下去到角色动,中间到底等了多久?”
输入缓冲(以及它的预输入场景)解决的是”我按了但没生效”的问题;输入采样解决的是”我按了但生效得不够快”的问题,也就是输入延迟。
先把 3 件事区分开:
- 输入什么时候到达引擎
- 输入什么时候被系统记录下来
- 游戏逻辑什么时候真正消费这个输入
这 3 件事不一定发生在同一个时刻。
游戏如何读取、记录和处理物理按键状态,这一整套过程就是这里讨论的输入采样问题。
最简单的情况(大多数中小项目就是这个方案):
flowchart LR
A["玩家按下攻击键"] --> B["等待下一次逻辑 tick"]
B --> C["逻辑系统读到当前按键状态"]
C --> D["检查角色当前是否可行动"]
D -->|是| E["攻击启动帧成立"]
D -->|否| F["本次输入失效
或交给缓冲系统处理"]
我自己初学时做的 Demo 就是这种做法——输入采样频率直接等于逻辑帧率。虽然能用,也不算错,只是后来看资料时才意识到,输入进入系统这一步还可以做得更细。
这类方案的特点是:简单、直观、好调试,但缺点也很明显——如果输入完全依附于逻辑 tick 才第一次被检测到,那么短输入更容易落在两次检测间隙里,输入延迟也更容易受整帧粒度限制。
更现代的一类做法,关键不在于“同一帧里额外读了几次”,而在于把输入拆成两个阶段:
- 输入事件先被记录
- 逻辑系统再在自己的 update / fixed update 里处理
玩家按键可以先作为一个带时间戳的事件进入系统,而不必等到下一次逻辑 tick 到来时才第一次记录。换句话说,输入模块先完成“记录”,逻辑系统再在自己的时机完成“处理”。
这种做法有两个主要好处:
- 不容易漏掉很短的按键
- 输入发生的时刻更贴近真实时间,而不是只能粗暴地按整帧对齐
这不等于逻辑判定本身突破了 60Hz。角色什么时候真正开始动作、判定什么时候真正生效,通常还是要等逻辑 tick 来处理这个输入。
所以这里重点讨论的不是“逻辑帧率有没有被提上去”,而是:
- 输入是否更早进入系统
- 输入是否更细粒度地被记录
- 输入从发生到被逻辑处理,中间有没有被不必要地拖慢
先看一个更完整的处理过程:单按键输入。
flowchart TB
A["玩家按下攻击键"] --> B["设备 / OS / 驱动传递输入"]
B --> C["输入进入引擎"]
C --> D["输入模块记录事件
AttackPressed(time=10ms)"]
D --> E["下一次逻辑 tick 读取事件"]
E --> F["检查角色当前是否可行动"]
F -->|是| G["本 tick 进入攻击启动帧"]
F -->|否| H["交给输入缓冲 / 预输入系统继续处理"]
这个例子里,逻辑系统处理的对象就是一个明确的输入事件:AttackPressed。它的处理动作也很直接:读取事件、检查条件,再把结果转成攻击启动、跳跃、闪避之类的具体游戏行为。
格斗游戏里的情况会更复杂一些。以《街霸 6》这类系统为例,逻辑层通常不会只处理“某一个按钮事件”,而是会处理一小段输入历史。系统先记录最近若干帧的方向键与按钮输入,再在逻辑 tick 中检查这段历史里有没有满足条件的指令模式。
flowchart TB
H["最近若干帧输入历史
↓ ↘ → P"] --> J["逻辑 tick 到来"]
J --> K["指令解析器读取输入历史"]
K --> L{"是否匹配 236P?"}
L -->|是| M["将这段输入判定为 236P
波动拳成立"]
L -->|否| N["保留输入历史
继续给普通攻击 / 下一条指令判断"]
这里的重点已经不是“把某个按键立刻变成动作”,而是把已经记录下来的输入,按游戏规则解释成一个可成立的结果。对于单按键系统,逻辑层处理的往往是一个事件;对于格斗游戏的指令系统,逻辑层处理的往往是一段输入历史。
从时间分布上看,这两种处理过程里真正被缩短的都不是“逻辑判定的间隔”,而是输入从发生到被系统记录下来的那一段等待。无论后面处理的是单个输入事件,还是一小段输入历史,逻辑系统都不用等到下一次采样时才第一次知道“刚才发生了什么输入”。后面真正还会继续占用时间的,主要只剩两段:一段是输入到达引擎前的设备 / 系统层传递,另一段是记录完成后等待下一次逻辑 tick。
输入采样和前面两个概念最核心的区别在于:它不负责“把输入存着等以后执行”,而是负责让输入更早、更准地进入系统。输入缓冲解决的是“后续执行时不要漏掉输入”;输入采样解决的是“输入不要太晚进入系统”。
3.4 概念对比
这三个”概念”实际对应两个维度——输入缓冲(含其预输入场景)和输入采样解决的是不同环节的问题:
| 输入缓冲(总称) | 预输入(缓冲的使用场景) | 输入采样 | |
|---|---|---|---|
| 一句话 | 按了之后暂时保留输入 | 还没到时机但先记录输入 | 让输入更早、更细粒度地进入系统 |
| 解决的问题 | ”我按了但没生效” | 同上,但场景更具体——在动作中提前按 | ”按下去到响应有延迟” |
| 处理对象 | 一次按键事件 | 一次按键事件 / 一串指令 | 物理按键状态、输入事件或输入历史 |
| 是否存储 | ✅ 存,有效期递减 | ✅ 存,直到当前动作结束 | 视实现而定:可能只是轮询,也可能先入事件队列 |
| 结束条件 | 固定帧数递减→过期丢弃 | 当前动作结束→自动执行 | 不讨论“存多久”,而是讨论“何时被记录、何时被处理 / 解析” |
| 典型实现 | buttonHeldFrames 计数器递减 | 输入队列 + 动作结束检查 | 逻辑 tick 轮询;或事件带时间戳进入队列后再处理 |
更详细的输入缓冲技术讨论可参考 Fighting Game Input Systems 和格斗游戏社区的 Grace Frame 研究。
3.5 两者可共存
输入缓冲(含预输入)和输入采样可以同时工作。完整链路里,输入要先经过物理设备和系统层,进入引擎以后才会被记录、解析和处理。很多现代输入系统,本来就是把这几步串在一起的:
flowchart TB
S0["① 玩家物理按键 / 搓招"] --> S1["② 设备与系统层传递
手柄 / 键盘 / 触屏 → OS / 驱动"]
S1 --> S2["③ 输入进入引擎
轮询读取或事件入队"]
S2 --> S3["④ 引擎记录输入
事件队列 / 输入历史"]
S3 --> S4["⑤ 逻辑帧处理
检查可行动状态 / 指令模式"]
S4 --> S5{"⑥ 当前输入如何处理?"}
S5 -->|可直接成立| S6["立刻执行动作"]
S5 -->|需等待时机| S7["放入输入缓冲 / 预输入"]
S5 -->|需继续匹配| S8["保留输入历史
等待下一次指令解析"]
S7 --> S9["条件满足 → 执行"]
S8 --> S4
S6 --> S10["结果输出"]
S9 --> S10
“输入采样”和“输入缓冲”不是二选一,很多时候都要结合使用:
- 前者负责让输入尽早进入系统
- 后者负责别让这个输入在可执行前过早丢失
到这里,第 3 章讨论的都还是游戏内部怎么读取、记录和处理输入。
但玩家按下按键以后,延迟并不只来自游戏内部。输入在真正进入游戏逻辑之前,设备、操作系统和显示链路本身也已经先带来了一段额外时间消耗。这个部分和输入采样不是同一层问题,仍需单独拆开看。
4. 设备与平台延迟——输入系统之外的硬约束
前文介绍的输入采样、缓冲和预输入,解决的都是”输入系统读到按键之后”的问题。但在按键被系统读到之前,还有不可忽视的一步——设备层面的输入延迟。
PC 端和移动端在这一步的差距相当大:
| 设备类型 | 输入→系统读到的延迟 | 说明 |
|---|---|---|
| 街机框体 | ~1-2ms | 专用硬件,几乎无额外延迟 |
| PC 键盘(1000Hz) | ~1-10ms | USB 轮询 1ms,加上开关去抖和扫描 |
| PC 鼠标(1000Hz) | ~2-10ms | 同上,高端游戏鼠标可更低 |
| 游戏手柄(有线) | ~5-17ms | 125Hz USB 轮询为主,部分支持 1000Hz |
| 移动端触屏 | ~35-140ms | 含触控采样、OS 处理、显示管线等全链路 |
移动端比 PC 端多出 30-80ms 甚至更多的延迟。这个差距来自触控采样、OS 事件分发和显示管线——不是输入系统能消除的。
《街霸 6》社区里有不少输入延迟测试图。下面这张 Demo 版本的对比图里,同一款游戏在不同刷新率和低延迟设置下,结果层延迟差得很明显。
更重要的是,它们整体都已经控制在很低的区间里。现代格斗游戏在输入延迟这件事上,通常会把整条链路尽量缩短。
所以移动端动作游戏的输入设计思路和 PC 端不同:
- PC 端可以设计 2-3 帧的精确窗口,因为设备延迟低,输入采样的误差可控
- 移动端需要避免这类极限窗口,因为触屏延迟本身就在几十毫秒量级,和窗口长度相当
- 移动端采用帧锁定方案(如第 2 章提到的《火影忍者》15Hz 逻辑帧)也是用低逻辑帧率来”吸收”触屏延迟——触屏延迟和逻辑帧等待在同一个量级,玩家分不清差距
这部分延迟是硬件和系统层面的硬约束。输入系统能做的,只是在它之后尽量少再损失几帧,没法把它本身抹掉。
到这里,“玩家按键”到”系统响应”之间的主要延迟来源已经交代清楚了。接下来讨论的不是输入链路,而是命中成立之后的表现处理:画面要不要停一下,动作要不要跳一下,打击感要怎么立起来。这就是顿帧要解决的问题。
5. 顿帧(Hit Stop)——命中瞬间的”停”和”跳”
命中瞬间,角色动画短暂停几帧,这个效果就是顿帧(又称卡肉、帧冻结)。动作游戏里很多攻击命中的重量感,都是靠它支撑的。
但顿帧的处理方式会引出几个问题:冻结哪些角色?只停攻击者还是受击者也要停?逻辑时钟走不走?多人联机时怎么保证A的顿帧不影响B的操作?下面整理了不同方案各自的取舍。
5.1 顿帧的基本直觉
命中瞬间,攻击方和受击方的动画各自短暂地冻结若干帧。玩家看到的是”这一刀砍进去,双方停了一下”——这个停顿制造了重量感。
具体停谁的方案在不同游戏中有所不同:
- 双方都停——攻击者和受击者的动画同时冻结,也是大多数动作游戏的做法。格斗游戏中攻击方可以在顿帧期间输入下一个指令做连段取消,受击方也可以通过特定操作微调受击位置(如 Smash Bros 的 SDI)。双方冻结的时长可以不同——Capcom 清版游戏(《快打旋风》《惩罚者》)中攻击者的顿帧通常比受击者短几帧。这样设计的意图是:攻击者先恢复行动,相当于给命中方一个帧数优势作为奖励,鼓励玩家主动进攻。
典型的案例:《街霸 2》的 Canceling Bug / Special Move Cancel
这类机制常被用来解释《街霸 2》的 canceling bug,也就是通常技命中后接出 special move cancel 的现象。就公开材料来看,更稳妥的说法是:开发组原本是在给必杀技输入增加宽容度,后来发现普通技命中后也能顺着这个机制接出必杀,于是把它保留了下来。到了玩家实际操作这一层,通常技命中后的 hit stop 又进一步拉长了可操作时间,所以取消会变得更容易。
结果就是:通常技命中 → 顿帧期间补完必杀输入 → 顿帧结束后必杀技立刻发出 → 连段成立。从机制上看,Capcom 后来的官方专栏补充了一个关键点:必杀技取消本来就是在 hit stop 期间完成的,顿帧越长,取消通常越容易。
- 仅停受击者——攻击者的动画不受影响,只有受击方被命中时短暂停顿。相当于用顿帧延长了受击硬直。一些动作游戏中攻击方做减速(hitsslow)、受击方做暂停(hitstop)的设计也属于这类思路。
至于仅停攻击者——一般不会有这样的做法。顿帧的核心目的是让玩家感知到”这一击打中了”,而感知的来源是受击方的反应。只停攻击者而受击方正常播放动画,玩家会感觉”我卡了一下,但敌人好像没受影响”,玩家反而会觉得影响手感。
双方都停是通用方案,仅停受击者则更强调受击反馈。具体选哪种取决于设计意图。
常见的顿帧时长(Celia Wagar 总结,2017):
- 轻击:2-3 帧(~33-50ms)
- 重击:5-8 帧(~83-133ms)
- 终结技/必杀技:10-15 帧(~167-250ms)
以《怪物猎人》里斩斧的纵劈(Overhead Chop)为例,不同作品之间的命中停顿差异就很直观:GU、World、Rise 都还能明显看到命中停顿,但 Wilds 这一下几乎已经压到接近 0 了。光看这组对比,还谈不上直接判断哪种更好,但拿它来建立“卡肉有多明显”的直觉很合适。
动态对比
完整演示视频:Monster Hunter hitstop 对比视频
5.2 单机场景的三种方案
| 方案 | 做法 | 逻辑/画面对齐 | 其他角色 | 实现复杂度 |
|---|---|---|---|---|
| A. 全局全停 | Time.timeScale = 0 | ✅ 完全对齐 | ❌ 全场冻住,其他角色也被暂停 | 最简单 |
| B. 角色级全停 | 只暂停该角色自身的 localTimeScale,逻辑和动画都绑在这个时间尺度上 | ✅ 对齐 | ✅ 其他角色正常活动 | 中等 |
| C. 只停动画 | animator.speed = 0,逻辑照常跑 | ❌ 恢复后动画落后逻辑 | ✅ 其他人正常 | 简单但后果严重 |
方案 B(角色级全停,逻辑和动画一起停):
| 时间 | 帧 10 命中 | 帧 11 | 帧 12 | 帧 13 | 帧 14 | 帧 15 恢复 |
|---|---|---|---|---|---|---|
| 逻辑帧 | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ▶️ 继续 |
| 动画帧 | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ▶️ 继续 |
→ 恢复后逻辑和动画都从帧 10 继续 → ✅ 始终对齐
方案 C 的问题:只停动画不停逻辑,恢复后动画和逻辑的时间轴就已经错位了。
方案 C(只停动画,逻辑不停):
| 时间 | 帧 10 命中 | 帧 11 | 帧 12 | 帧 13 | 帧 14 | 帧 15 恢复 |
|---|---|---|---|---|---|---|
| 逻辑帧 | 10▶️ | 11▶️ | 12 ▶️ | 13▶️ | 14▶️ | 15▶️ |
| 动画帧 | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ⏸️ | 10 ▶️ 继续 |
→ 判定在 12 帧激活时,动画还在 10 帧 → ❌ 判定和画面错位,角色动作没跟上判定
方案 C 如果顿帧只有 1-2 帧、且后续没有复杂的连段衔接,可能不出问题。但顿帧拉长到 5 帧以上,或者后续有精确的连段窗口,画面和判定就会开始打架。
不过方案 C 加一个跳帧对齐就能修:顿帧结束后动画不从暂停处继续,而是直接跳到逻辑时钟对应的帧位置。
| 时间 | 帧 10 命中 | 帧 11~14 | 帧 15 恢复 |
|---|---|---|---|
| 逻辑帧 | 10 | 11→14 | 15 |
| 动画帧 | 10 ⏸️ | 10 ⏸️ | 跳到 15 ▶️ |
我个人常用的是方案 B(角色级全停)。方案 B 的逻辑更干净——其他非角色系统(如 UI、摄像机)可以继续运行,不会因为顿帧而全部暂停。在没有特殊的抽帧要求时,这种设计会更加方便实用一些。
5.3 多人/共斗时,顿帧的处理方式完全不同
多人同时打 Boss 时,方案 A 和方案 B 都不好使——玩家 A 的命中不能把玩家 B 的游戏逻辑帧也停掉。
顿帧的处理方式取决于网络架构,不存在通用的”正确答案”。
| 网络架构 | 代表游戏 | 顿帧方案 | 原理 |
|---|---|---|---|
| Client-Server 服务器跑逻辑,客户端跑渲染 | MHW、共斗游戏 | A. 本地视觉停帧 每个客户端各自停自己的,互不影响 | 顿帧和震屏是同类——服务器不管视觉反馈,客户端收到”命中”事件后本地自产。但攻击者的卡肉动画会通过网络同步,所以你能看到队友命中时他的角色卡了一下、Boss 也卡了一下——不过你的操作不会因此被冻结 |
| 确定性锁步 所有客户端输入一致、逻辑一致 | 格斗游戏 1v1 本地联机 | B. 双方同时停帧 顿帧时长为游戏逻辑的一部分,所有客户端在同一帧起止 | 双方被冻结相同时间,不影响公平性。甚至可被用作连段取消窗口(如 SF2 的 special move cancel) |
| 回滚网络 客户端预测→服务器确认→回滚修正 | SF6、GGST 现代格斗 | A. 确认后触发 顿帧不做预测,等服务器确认命中后才播放 | 预测阶段的顿帧会在回滚时重复计算,导致帧数错乱 |
| 状态同步 服务器低频同步,客户端本地插值 | 手游/MMO 共斗 | A. 本地视觉停帧 服务器同步频率(5-10Hz)远低于帧率,没条件做全局顿帧 | 顿帧方案 B 和 C 在此架构下都经不起推敲 |
关于方案 B(双方同时停帧)在锁步架构以外的尝试——如果用在 Client-Server 共斗里,逻辑上行不通:
- A 命中 Boss 时通知服务器”停 1 帧”,服务器广播给所有玩家
- 但玩家之间的网络延迟不同,有人收到通知时那 1 帧已经过了
- 更根本的问题:B 的蓄力/闪避节奏被 A 的命中打断——把自己的打击感建立在打断队友操作上,不符合共斗的设计目标
关于方案 C(纯特效替代)——技术上可行,但失去了顿帧这个最直接的”打中了”信号,需要足够强的震屏、音效和命中特效来补足打击感,否则就会像 MH Wilds(2025)那样被老玩家吐槽”手感飘”。
方案 B 的具体画面:
玩家 A 命中 Boss:
A 的客户端 → Boss 在 A 的屏幕上视觉停了 3 帧 + 震屏 + 特效
B 的客户端 → Boss 正常动,B 正常打,不受影响
服务器 → Boss 逻辑不暂停,伤害正常结算,AI 正常决策
为什么不能在 Boss 的逻辑层停?如果 A 和 B 连续交替命中,Boss 的逻辑帧会被反复暂停——A 停 3 帧,B 停 3 帧,Boss 永远跑不动。所以多人模式下的顿帧只能在视觉表现层做。
5.4 风格化抽帧——表现手法,而非性能问题
性能掉帧是 GPU 性能不足时的被动结果。风格化抽帧则是一种视觉上的主动选择——命中顿帧结束后,收招/受击动画故意跳过中间过渡帧,让角色从一个关键姿势直接切到下一个关键姿势。
这样做的目的是通过”先慢后快”的对比来放大感官体验:
- 顿帧制造重量——命中瞬间停下来,让玩家感受到”这一刀砍中了”
- 抽帧抢回节奏——停完后跳过中间过渡帧,把顿帧消耗的时间补回来,让动作看起来更快
两者合在一起就是:先慢(突出力量)→ 再快(保持节奏),用对比来放大这一击本身的力度感。
和性能掉帧的区分:
| 性能掉帧 | 风格化抽帧 | |
|---|---|---|
| 原因 | GPU/CPU 性能不足,被迫跳帧 | 动画师主动去掉中间帧 |
| 表现 | 随机、不均匀 | 节奏稳定,每一跳都是设计好的 |
| 对逻辑层的影响 | 渲染延迟可能影响输入采样 | 无影响——逻辑帧照常跑 60fps |
| 目的 | 无(被迫的) | 模仿手绘动画的 Limited Animation 风格 |
Arc System Works(《罪恶装备 Xrd》《龙珠斗士Z》)是这类做法里最典型的一支。
ArcSys 在 GDC 2015 上公开了他们的做法(演讲者:本多淳也):
普通 3D 动画的工作流是:动画师摆关键帧 → 引擎自动算中间帧 → 平滑过渡。我们发现这样看起来太”3D”了,不像 2D 动画。所以我们关掉了插值。每个姿势都是动画师手动调的,引擎不能在中间插任何东西。
这张图把取舍摆得很清楚:左边的 Full 更平滑,但更像普通 3D;右边的 Limited 主动减少中间过渡帧,姿态变化更“硬”,也更接近传统 2D 动画的阅读感。ArcSys 选的是后者,因为动作轮廓更明确,节奏也更鲜明。
拆开看,它做的是:
- 关掉 3D 动画引擎的自动插值功能
- 每一帧都是动画师亲手调的关键姿势
- 角色动画的实际帧率降到了 ~12-24fps(模仿手绘动画的”一拍三”)
- 但背景和摄像机仍然以 60fps 运行,玩家不会觉得头晕
- 逻辑和判定也仍然是 60fps,手感不受影响
普通 3D 动画:帧1 ──插值── 帧2 ──插值── 帧3 ──插值── 帧4(连续平滑)
ArcSys 风格: 帧1 ────────── 帧3 ──────────── 帧6 ───── 帧10(跳跃)
每帧都是关键帧,没有中间过渡
放成动态素材之后,这个区别会更明显:Full 是连续补足中间帧,Limited 则会稳定地跳过一部分过渡姿态。看上去像“卡”,但它的节奏是稳定的,也是设计出来的,这才是它和性能掉帧的区别。
玩家看到的是:角色像动画片一样一帧一帧地动,背景和镜头还是顺的,操作手感也没丢。第一次玩《龙珠斗士Z》或者《罪恶装备》系列时,很多人都会觉得“这游戏是不是有点卡?”但这并不是性能卡顿,而是有意为之。
再收窄到单次打击的局部表现,有些动作游戏里的重攻击会更接近另一种观感:不是把整套动画都做成 Limited Animation,而是在命中那一小段里,先用顿帧表现冲击感,再让动作迅速过渡到一个更有力的后续姿态。《鬼泣 5》里但丁拳套蓄力攻击的观感就很接近这一类处理。
这个例子里,命中后渲染层并不是严格按照序列帧执行,而是更像先停一下,再把中间过渡姿态压掉一部分,直接把角色和受击者推到更夸张的后续关键姿态上。这样一来,重量感和爆发感能有明显提升。
不过这一步只能停留在表现层推断:从观感上看,它很接近“顿帧后压缩中间帧、直接落到关键姿态”的方案;至于《鬼泣 5》底层是不是我前面说的那种“顿帧后直接跳到某个渲染帧”,还不能完全确定。
6. 高渲染帧率下的中间帧显示——逻辑帧之间画什么
前面讲 Guilty Gear 和《鬼泣 5》时,讨论的是动作表现本身要不要保留中间姿态;这一节讲的是另一件事:当渲染帧率高于逻辑帧率时,引擎在两次逻辑更新之间拿什么去画屏幕。这更接近显示层的问题,不是动画师是否手动插关键帧的问题。
当渲染帧率高于逻辑帧率时(比如逻辑 60fps、渲染 120fps),两次渲染帧之间往往没有新的逻辑结果。如果完全不补中间结果,引擎就只能连续显示同一个逻辑状态;这样虽然逻辑没错,但高速运动时会显得更生硬。
常见做法主要有两类:
- 插值:在前后两个已知状态之间补一个中间显示结果。比如第 10 帧角色位置在 x=0,第 11 帧在 x=10,那么渲染中间帧时可以先画在 x=5。这样画面更平滑,但前提是你已经知道“下一帧会到哪里”,所以显示结果天然会比最新逻辑状态晚半步。
- 外推:根据当前状态去预测下一小段时间内的结果。比如第 10 帧位置在 x=0、速度朝右,那么中间渲染帧先预测它会继续往右移动。这样不必等待下一帧逻辑结果,但如果角色突然转向、停下或切动作,预测就会出错,画面可能出现短暂跳变。
对动作游戏来说,关键不在于“用不用插值”,而在于哪些内容可以放心交给自动补间,哪些内容不能。摄像机、远景对象、一般位移平滑,通常比较适合做插值或外推;但对战斗判读最关键的角色攻击姿态、受击姿态和命中反馈,设计上往往不会把结果完全交给自动补间。原因不是动作游戏“不用插值”,而是这些关键姿态一旦补错,玩家对时机、距离和打击感的判断就会一起变形。
7. 两个工程上的习惯
7.1 所有帧数用时间存储
踩了很多和帧数有关的坑以后,这里做一个提醒:所有帧数窗口尽量用时间(毫秒)存储,不要写死成”几帧”。
// 这个 8 帧只在 60fps 下是 133ms
// 如果逻辑帧改成了 30Hz 或 120Hz,含义就变了
// float parryWindow = 8f;
// 用时间定义意图——133ms 在不同逻辑帧率下自动换算
float parryWindow = 0.133f;
int framesInCurrentTickRate = Mathf.RoundToInt(parryWindow / Time.fixedDeltaTime);
7.2 角色级时间缩放
如果项目需要做顿帧、子弹时间、慢动作等效果,可以搭建角色级的时间缩放系统:
每个角色/对象有一个 localTimeScale
叠加上全局的 globalTimeScale
最终有效时间 = 全局时间 × localTimeScale
这个系统影响的范围:
- 动画播放速度(
animator.speed = localTimeScale) - 角色内部的计时器(连段窗口、CD)
- 粒子系统(
particleSystem.main.simulationSpeed = localTimeScale)
不影响的:
- AI 决策
- 物理引擎(可选项——取决于要不要在顿帧期间也冻结物理)
- 全局输入采集
这样就能做到:“玩家 A 被重击命中,视觉上停了 5 帧,但玩家 B 的 AI 还在决策,粒子仍在飘散,输入仍然可以被采集”。
资料来源
本文引用的数据来源列表,方便查验和进一步阅读:
- Woods et al., “Factors influencing the latency of simple reaction time”, Frontiers in Human Neuroscience, 2015 — 大规模简单反应时研究(n=1469),含硬件延迟校正。https://pmc.ncbi.nlm.nih.gov/articles/PMC4374455/
- Bragança et al., OEPF 2021 — 游戏玩家(>5h/周,~251ms)vs 非玩家(~293ms)手机 app 简单反应时对比。https://www.oepf.org/wp-content/uploads/2021/01/OVP-11-3-Braganca-Final.pdf
- Bickmann P, Wechsler K, Rudolf K, et al., “Comparison of Reaction Time Between eSports Players of Different Genres and Sportsmen”, IGI Global, 2021 — Vienna Test System 测量职业电竞选手(~249ms)与传统运动员(~257ms)的简单视觉反应时对比。https://www.igi-global.com/gateway/article/274054
- Luu A, Winans A, Suniga R, Motz VA, “Reaction Times for Esport Competitors and Traditional Physical Athletes are Faster than Noncompetitive Peers”, Ohio Journal of Science, 2021 — 电竞选手(~269ms)vs 大学运动员(~276ms)vs 非运动员对照组(~305ms)反应时对比。https://doi.org/10.18061/ojs.v121i2.7677
- Celia Wagar, 2016 — 格斗游戏帧数窗口对应手感实测(Frame Trainer)。https://critpoints.net/2016/08/19/frame-trainer-tool-how-long-are-frames/
- Celia Wagar, 2017 — 顿帧(Hitstop)的原理与游戏中的应用。https://critpoints.net/2017/05/17/hitstophitfreezehitlaghitpausehitshit/
- KI Infil Guide — Killer Instinct 社区的反应时与帧数窗口分析。https://ki.infil.net/reaction.html
- Wavu Wiki (Reacting) — Tekken 社区的反应阈值框架(i20+ / i23+ / i26+)。https://wavu.wiki/t/Reacting
- UMGamer, “60Hz and 120Hz monitors: practical differences in fighting games”, 2025 — 引用 WydD 测试数据:60Hz 约 83ms 延迟、120Hz 约 37ms。https://umgamer.com/en-us/articles/60hz-and-120hz-monitors-what-are-the-practical-differences-in-fighting-games
- Arc System Works, GDC 2015 — 本多淳也《Guilty Gear Xrd’s Art Style: The X Factor Between 2D and 3D》。https://www.youtube.com/watch?v=yhGjCzxJV3E
- Fighting Game Input Systems — 格斗游戏输入缓冲与指令处理的实现分析。https://pangaea.neocities.org/post/fighting-game-input-systems/
- Grace Frame 研究 (Osaka City University, 2025) — 格斗游戏指令输入宽容帧的学术研究。https://www.ite.or.jp/ken/paper/20250310cAnk/eng/
- Unity Blog, 2026 — 关于帧轮询输入可能丢失的官方说明。https://unity.com/blog/input-system-event-driven-architecture-for-scalable-controls
- Simplified Media (Input Buffer Guide), 2026 — 输入缓冲的完整实现分析。https://simplified.media/guides/input-buffer-browser-games
- 3DM / Axelayer (MH Wilds Hitstop 对比), 2024 — MHW 卡肉 13 帧、MHR 15 帧、MH Wilds 0 帧的数据对比。https://www.3dmgame.com/news/202411/3907893.html
- Shane Sicienski, “Hitstop in Capcom Beat ‘Em Ups”, 2025 — Capcom 清版游戏顿帧分析:只停攻击者和受击者,不影响其他对象。https://shane-sicienski.com/blog/blog-post-title-one-55pmn
- GamesRadar / MH Wilds 总监德田优也访谈, 2024 — 荒野移除卡肉的决策依据及 Beta 后回调。https://www.gamesradar.com/games/monster-hunter/monster-hunter-wilds-hitstop/
- GamineAI, “Rollback Netcode Explained”, 2026 — 回滚网络最佳实践:hitstop 应在确认后触发,不做预测。https://gamineai.com/blog/rollback-netcode-explained-implementing-responsive-multiplayer-combat
- 夏天, “多人游戏中的同步机制综述”, 2020 — 将顿帧列为本地延迟隐藏手段(“顿帧、震屏、受击假特效”)。https://zsummer.github.io/2020/07/24/2020-07-24-state_sync/
- 腾讯云, “格斗类帧同步游戏的优化” — 逻辑与渲染分离,受击表现归客户端渲染层处理。https://cloud.tencent.cn/developer/article/1006347
- 火影忍者项目组技术分享, “帧锁定同步方案”, CSDN/博客园 — 逻辑帧率 15Hz(66ms),可靠 UDP + 冗余重传,不使用客户端预测。https://blog.csdn.net/qq_18536721/article/details/52713564
- Wimmer et al., “On the Latency of USB-Connected Input Devices”, Uni Regensburg — 36 款键盘/鼠标/手柄的 USB 输入延迟实测(1000Hz 轮询下鼠标约 2ms,键盘约 1-10ms)。https://epub.uni-regensburg.de/40182/
- GameBench, “Touch Latency Benchmarks: iPhone XS Max vs Galaxy Note 10”, 2019 — 移动端触屏输入延迟实测(PUBG Mobile 等四款游戏,平均 78-95ms)。https://blog.gamebench.net/touch-latency-benchmarks-iphone-xs-max-galaxy-note-10
- Kamarainen et al., “A Measurement Study on Achieving Imperceptible Latency in Mobile Cloud Gaming”, MMSys 2017 — 触屏到内核延迟约 24-40ms,游戏手柄到内核约 0.6ms 的对比数据。https://2017.acmmmsys.org/wp-content/uploads/2017/05/Teemu-Kamarainen.pdf
- Game Developer, 2013 — 对西谷亮相关发言的英文转述;用于说明《街霸 2》取消 bug 最初来自”让必杀技更容易输入”的宽容处理。https://www.gamedeveloper.com/business/-i-street-fighter-ii-i-designer-opens-up-about-the-cancelling-bug-
- CAPCOM: Shadaloo C.R.I., “Hour 14: The Basics of Combos: Cancels”, 2019 — 官方机制说明:必杀技取消是在 hit stop 期间完成的,顿帧越长,取消通常越容易。https://game.capcom.com/cfn/sfv/column/132455?lang=en