帧间隔
原版 Scratch 的速度和帧率绑在一起:「重复执行」里放一块 移动 10 步,30 帧时每秒 300 步,
60 帧时每秒 600 步,作品一卡、帧率一掉,角色也跟着变慢。
侦测类里的三块积木把速度和帧率分开。写成 移动 (每秒 (300)) 步,角色在任何帧率下都是
每秒 300 步:30 帧、120 帧、加速模式、作品卡到只剩 20 帧,走的距离都一样。游戏引擎里
这叫 delta time(dt)。

计时器下面依次是「帧间隔(秒)」「每秒 ()」「实际帧率」。
三块积木#
| 积木 | 返回 |
|---|---|
| 帧间隔(秒) | 距离上一轮过去了多少秒。60 帧时约 0.0167 |
| 每秒 () | 填进去的数 × 帧间隔。放进循环里,一秒累加下来正好是填的那个数 |
| 实际帧率 | 最近这段时间每秒真正跑了多少帧,保留一位小数 |
「帧间隔」和「实际帧率」可以勾选,在舞台上显示成监视器。
怎么用#
凡是「每帧走一点」的积木,都把数值换成「每秒 ()」:
| 原来的写法 | 改成 |
|---|---|
移动 10 步 |
移动 (每秒 (300)) 步 |
右转 15 度 |
右转 (每秒 (450)) 度 |
将 x 坐标增加 5 |
将 x 坐标增加 (每秒 (150)) |
将 速度 增加 -1(重力) |
将 速度 增加 (每秒 (-900)),再 将 y 坐标增加 (速度 × 帧间隔) |
换算方法:原来的数 × 原来按的帧率。按 30 帧写的 移动 10 步 就是每秒 300 步。
「在 () 秒内滑行到」「等待 () 秒」这类本来就按时间算的积木不用改。
细节#
按「轮」计算#
一帧里调度器可能跑好几轮:没有脚本请求重画时(比如循环里只改变量),以及加速模式下, 同一帧内会连跑多轮,每一轮每个脚本的循环体执行一次。帧间隔按轮计算,所以所有轮的帧间隔 加起来严格等于真实流逝的时间,一帧跑几轮都不影响速度。
第一轮#
点绿旗、停止、从暂停恢复、改帧率之后的第一轮,帧间隔按作品帧率算(60 帧就是 1/60 秒), 不把暂停或停下的那段时间算进去。帧率设为「不限」时按 60 算。
上限 0.1 秒#
帧间隔最大 0.1 秒。切到别的标签页时浏览器会把作品降到一秒一帧,切回来那一轮如果按 1 秒 算,角色会一步跨过墙壁。超过上限就按 0.1 秒算,代价是:作品实际跑不到 10 帧时,游戏 整体变成慢动作。10 帧以上速度都是准的。
不刷新屏幕的循环#
「运行时不刷新屏幕」的自制积木在一轮里整个跑完,里面每一圈拿到的帧间隔都一样。在这种 循环里做物理分步时,要自己把帧间隔分成若干份。
和补帧的关系#
两者解决的是不同的问题。帧间隔让速度与帧率无关;补帧让低帧率下的 画面更顺。可以同时使用。
和积木栏默认值的关系#
积木栏里 移动 10 步 这类积木的默认值按作品帧率折算(60 帧时是 移动 5 步),让拖出来的
积木速度和原版 30 帧一致。它们仍然随帧率变化;要与帧率无关,用「每秒 ()」。
扩展里读取#
扩展可以直接读运行时上的两个字段:
| 字段 | 含义 |
|---|---|
runtime.deltaTime |
帧间隔,单位秒,规则同上 |
runtime.measuredFramerate |
实际帧率,未取整 |