Verse Wiki — 写给 UE6 时代的 Verse 互动手册
拓展 · EXTRA

Sleep 的真实计时:30 tick 上限与逐帧动画

你写 Sleep(0.01),引擎却按 1/30 秒给你结账。本页整理社区实测数据,告诉你 Sleep 在真实服务器上到底睡多久,以及做平滑动画时为什么「Sleep(0.0) 就完事了」,连 DeltaTime 都常常不用算。

一、实测数据:Sleep 并不按你写的睡

Epic 开发者论坛帖《Important Notes On Sleep & UEFN Timing》做了一件朴素而宝贵的事:实机测量。作者在循环里放不同参数的 Sleep(就是蓝图里那个 Delay 节点),数每秒实际执行多少次,结论非常干脆——Sleep(0.1) 稳定得到每秒 10 次;而 Sleep(0.01)Sleep(0.0) 都封顶在每秒约 30 次,作者在最慢与最快的测试设备上跑,结果一致。

原因正是第 19 课讲的模拟帧:Fortnite 服务器每秒约 30 次模拟更新,Sleep 只能在帧边界醒来,亚帧精度根本不存在。你写进括号的数字更像一个「下限申请」:引擎保证至少睡这么久,然后在下一个帧边界叫醒你。对照表如下:

你写的代码 实际执行频率 说明
Sleep(1.0) 约每秒 1 次 正常按秒计时
Sleep(0.1) 约每秒 10 次 正常,10 ≤ 30 装得下
Sleep(0.01) 约每秒 30 次(封顶) 想要 100 次?引擎只给 30
Sleep(0.0) 约每秒 30 次(逐帧) 「下一帧叫我」,与 0.01 实际等效

二、实用结论:逐帧动画直接 Sleep(0.0)

要用 Verse 做平滑移动、渐变、逐帧动画,别纠结「该睡多久」——直接写 Sleep(0.0),即每帧执行一次、约 30fps。这样意图最清晰:「我要逐帧做事」,而不是伪装成某个精确毫秒数。更省心的是,由于 tick 率被引擎调控且基本恒定,帖子作者的经验是通常不需要自己计算 DeltaTime:每帧挪一个固定步长,视觉上就是匀速运动。

用第 19 课的「loop + Sleep」模板写一个逐帧计数器,亲手验证 30 tick 这件事:

frame_counter_device.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

frame_counter_device := class(creative_device):

    OnBegin<override>()<suspends>:void =
        var Frames:int = 0
        loop:
            set Frames += 1
            if (Frames >= 90):
                break
            # 每帧让出一次:约 30 帧 = 1 秒
            Sleep(0.0)
        Print("数到 {Frames} 帧,墙上时钟大约走了 3 秒")

读图翻译:这就是第 19 课那套循环——一条绕回自己的执行线,每圈先用 Set 把 Frames 加 1,再用 Branch 判断 Frames 是否到 90、到了就 Break 跳出;没到就走一个 Sleep(0.0)(时长为 0 的 Delay,等于「下一帧再来」)。跳出后用 Print String 报告一共数了多少帧。

把它拖进关卡运行:从 OnBeginOnBegin(Event BeginPlay) 到打印,真实时间约 3 秒——90 帧 ÷ 30 帧每秒。如果你把 Sleep(0.0) 换成 Sleep(0.01),结果几乎不变;换成 Sleep(0.1),就要等约 9 秒。数字不会骗人:决定节奏的是帧,不是你写的毫秒。

最后一盆冷水:帖子里也有人提醒,30 tick 对某些高速动画并不够平滑——子弹拖尾、快速镜头运动在 30fps 下会有可见的顿挫。这是引擎层面的硬限制,Verse 层无法突破;设计高速视觉效果时,要么接受 30fps,要么改用引擎侧的非 Verse 方案来表现。

顺手总结三条可以直接抄进项目的经验:第一,凡是「每 X 秒触发一次」的玩法逻辑(刷怪、回血、积分结算),X 在 0.1 秒以上时 Sleep 都很可靠,放心用;第二,凡是「逐帧」的表现逻辑,统一写 Sleep(0.0),并按 30fps 来标定每帧步长;第三,别靠数 Sleep 的次数来累计精确的真实时长——每次唤醒都可能对齐到帧边界,误差会一圈圈累积,对时长敏感的玩法要留出容差。

想让一段 Verse 驱动的移动动画尽可能平滑,循环里应该写哪个?

来源

本文整理自 Epic 开发者论坛的社区实测: