性能,附带凭据
这些是 Weft 解算器的实测、公开实机数据,而非营销说辞。每一个数字都来自在一台特定机器上对发行代码实际运行 Stopwatch 所得,其内容原样刊在这里。据我们调查,没有竞品发布过这样公开实机、按平台细分的基准测试,所以请把公开本身也当作要点之一,而不只是数字。
测量所用的机器。 Intel Core i9-14900KF,物理核心 24,逻辑处理器 32,RAM 64 GB,Windows 11 Pro (build 26200),Unity 6000.3.9f1,Burst 1.8.29。测量日期 2026-07-12。
Weft 的开销,说人话
买家实际会问的四个场景,各自在上方公开的机器上的开销,以及在 90 fps VR 一帧(11.11 ms)中所占的比例。这是发行版构建(IL2CPP)的数字,也是规划场景时该参照的诚实数字。
| 你的场景 | Weft 解算器开销 | 占 90 fps VR 一帧的比例 |
|---|---|---|
| 一个主角角色(头发加一件服装) | ~0.6 ms | ~5% |
| 8 个角色的房间,全部静止 | ~2.8 ms | ~25% |
| 8 个角色的房间,你的手按在一个角色上 | ~4 ms (p95) | ~35%, 0 dropped frames measured |
| 一万顶点的服装正在生成 | ~4.5 ms one-time (with Bake Topology) | budget once per avatar join, not per frame |
几条值得了解的诚实提醒。这是在一台公开的桌面机器上测得,你自己的机器会有所不同。设备端(Quest、移动端)性能尚未测量。"被触碰的房间"一行使用的测量方式比"静止的房间"一行更轻量,所以不要把两者逐帧直接比较。完整的公开表格与测量方法在本页下方,这张表是叠加在它们之上的说人话前台。
它如你所愿地扩展
每个角色步进各自独立的世界,所以增加角色带来的开销几乎只是线性增长。没有意外的悬崖。发行版构建(紫色)在每一点都落在编辑器上限(粉色)之下。
上面的数字是逐个依次解算每个角色所得,是诚实的最坏情况。Weft 也可以把它们重叠起来解算:静止的八个角色一群大约快一倍,就连有人正触碰的角色,如今也和其余角色重叠运行。完整数字在下面。
把静止的一群一起解算
把静止的 8 个角色的房间一起解算而不是逐个解算,开销大约会减半。
这个阶梯里的每套装配是一个头发组(35 发丝,210 粒子)加一件 3,000 顶点的服装,每个角色约 3,210 个模拟点,8 套装配共 25,680 个。
只要没人触碰,Weft 就能同时解算多个角色,而不是一个接一个。下表就是在与本页其余部分相同的机器、相同的日常环境下,对这一点的实测。
测量日期 2026-07-12 / 2026-07-13。
本表的每个数字都是没人触碰的静止一群。有人抓住或戳一个角色时,Weft 如今会把它和这一群一起解算,而不是为它停下,所以触碰一个角色不再卡住这一帧(一个罕见情形除外)。被触碰时的数字在下一节,用的是另一种测量方式,所以不要拿它和本表逐格相比。
| 装配 | Sequential ms | 并发 ms,批处理关 | 并发 ms,批处理开 | 加速比,批处理关 | 加速比,批处理开 |
|---|---|---|---|---|---|
| 1 | 0.7027 | 0.5866 | 0.5986 | 1.1979x | 1.1739x |
| 2 | 1.4632 | 0.9016 | 0.8819 | 1.6229x | 1.6592x |
| 4 | 2.9021 | 1.6309 | 1.6059 | 1.7794x | 1.8072x |
| 8 | 5.7515 | 2.8688 | 2.8261 | 2.0049x | 2.0351x |
说白了,静止的一群在一个角色时快约 1.2 倍,八个时略高于两倍,批处理开或关都没有实质差别。静止的一群越大,重叠解算带来的好处越多。
Sequential 列是把同一群角色逐个解算,用的是同一种测量方式,所以加速比是同等条件下的比较。它不是本页前面那组普通多角色数字,那组测量方式略有不同,因此不要把两者等同。
两列加速比(批处理开与关)彼此都落在测量噪声之内,可视为同一结果。
在真实手机和头显上的数字目前还没有。它们所等待的工作已经完成,两台设备也已在手,只是还没测量。一旦测过就会补上。
当一只手真的按在角色身上时
即使房间里每个角色同时被抓、被戳、被压,也大约只要 4 ms。
这个阶梯中的每个世界,服装和头发上都各有一个握持中的抓取,加上一个从第一帧起就真正相交的碰撞体,给每个角色施加真实的戳刺冲量。
前面的表都是静止的一群。这一节正相反:每个角色从第一帧起就被抓、被戳、被压。它显示当玩家的手真的按在角色上时,一个场景到底要花多少。
测量日期 2026-07-13。
| 角色 | 常见 ms | p95 ms | p99 ms | 超过 90 fps 的帧 |
|---|---|---|---|---|
| 1 | 0.8043 | 1.4329 | 1.6742 | 0 |
| 2 | 1.1817 | 1.4355 | 1.4836 | 0 |
| 4 | 2.0224 | 2.5007 | 2.6737 | 0 |
| 8 | 3.5850 | 3.9533 | 4.0940 | 0 |
即使八个角色同时被触碰,也没有一帧超出预算。这是一台机器上的一次运行,而不是像其他表那样的多次平均,所以请当作好兆头而非承诺。更繁忙的场景会更贵。
p95 和 p99 是最坏情况读数,而非平均值:大约每二十帧、每一百帧才会有一帧比它更慢。最后一列统计的是"卡顿"帧数,即比 90 fps 头显给你的 11.11 ms 更慢、慢到会让人明显看出掉帧的帧数。
一点提醒:这与上面的静止表测量方式略有不同(同样的解算器工作,但去掉了周围的渲染),所以不要把两张表逐个数字相比。
角色加入时的一次性开销,以及已出货的解决方案
下面每一档都是在角色实例化时测得的一次"从零构建"World Build,不是每帧开销。
上面的一切都是每帧要付的开销。这一节不同:它是角色出现的那一刻构建它的一次性开销,就像一个玩家在会话中途走进场景。它只发生一次,而不是每帧,这里同时展示诚实的卡顿和 Weft 已出货的解决方案。
测量日期 2026-07-13。
| 发丝 | 构建 ms |
|---|---|
| 35 | 0.0956 |
| 70 | 0.1847 |
| 140 | 0.3708 |
| 200 | 0.5938 |
头发
| 顶点 | 构建 ms |
|---|---|
| 3,000 | 23.0921 |
| 4,875 | 47.2207 |
| 7,200 | 95.5325 |
| 10,000 | 193.8801 |
网格服装
| 装配 | 构建 ms |
|---|---|
| 1 | 23.0552 |
| 2 | 46.0327 |
| 4 | 92.5230 |
| 8 | 189.2070 |
多角色
头发构建起来很便宜。开销在服装网格上:一件现实的一万顶点服装从零构建大约要 194 ms,如果全都压在角色出现的那一瞬间,就是几帧的真实卡顿。这是未烘焙的诚实数字,解决方案见下文。
拓扑烘焙,已出货的解决方案
一次点击就能把一万顶点档位的从零构建从 ~198 ms 降到 ~4.5 ms,快了roughly 44x。
服装检查器上的"Bake Topology"按钮,会把构建服装中开销最大的部分(哪些顶点如何相连)一次性烘焙进一个保存的资源,此后每次角色加入时直接加载它,而不是从零重新推导。无铰链的网格阶梯在一万顶点档位从 ~198 ms 降到 ~4.5 ms,快了roughly 44x。启用铰链的服装在同一档位也有明显收益,从 ~500 ms 降到 ~55 ms,快了roughly 9 to 10x。姿态、缩放与调参的更改都不会使烘焙失效,只有对网格本身或拓扑设置的真正改动才会,其结果已被证明与未烘焙的构建逐字节相同。
过期或不匹配的烘焙永远不会被使用。Weft 会静默回退到从零构建,所以烘焙永远不会出货错误或损坏的结果。
分配为零,而且是一道门禁
Weft 的解算在稳态下,无论头发、网格布料还是多角色,每帧只分配零个托管字节。这不是愿望,而是一道硬性测试门禁,要求精确的零字节差且不留容差。差值非零,构建就会高声失败。它绝不会被悄悄放过。
完整阶梯
每一档、两列都在,以及精确的内存占用。解算器步进时间的中位数以毫秒计。百分比按 90 fps 计。
头发 一群发丝,每根发丝六个粒子。
即使 200 根发丝也很便宜,不到 0.5 毫秒。
| 发丝 | 粒子 | 编辑器 ms | 构建 ms | 90 fps | 内存 |
|---|---|---|---|---|---|
| 35 | 210 | 0.1262 | 0.1078 | 1.14% | 9,520 B |
| 70 | 420 | 0.2652 | 0.2388 | 2.39% | 19,040 B |
| 140 | 840 | 0.4644 | 0.3746 | 4.18% | 38,080 B |
| 200 | 1,200 | 0.4922 | 0.3792 | 4.43% | 54,400 B |
每粒子字节数在整个阶梯上保持不变。对于每档没有额外开销的固定粒子结构体来说,本就该如此。
网格服装 一张平坦网格,每个四边形两个三角形。
即使一件现实的一万顶点服装也只要约 1.3 毫秒。
| 顶点 | 粒子 | 编辑器 ms | 构建 ms | 90 fps | 内存 |
|---|---|---|---|---|---|
| 3,000 | 3,000 | 0.6794 | 0.5186 | 6.12% | 373,536 B |
| 4,875 | 4,875 | 0.8379 | 0.6218 | 7.54% | 610,656 B |
| 7,200 | 7,200 | 1.0314 | 0.7760 | 9.28% | 905,376 B |
| 10,000 | 10,000 | 1.2947 | 0.9183 | 11.65% | 1,260,896 B |
每粒子字节数沿阶梯略有上升,这是因为网格越大,每顶点的弯曲(铰链)约束密度会略微增加,而非来自每档的固定开销。
多角色 每套装配是一个头发组加一件服装。
8 个完整角色逐个解算约要 6.5 毫秒,这是静止或被触碰的群体实际上都不必全额支付的诚实最坏情况。
| 装配 | 粒子 | 编辑器 ms | 构建 ms | 90 fps | 内存 |
|---|---|---|---|---|---|
| 1 | 3,210 | 0.8076 | 0.6086 | 7.27% | 383,056 B |
| 2 | 6,420 | 1.5975 | 1.2395 | 14.38% | 766,112 B |
| 4 | 12,840 | 3.2479 | 2.4832 | 29.23% | 1,532,224 B |
| 8 | 25,680 | 6.4776 | 5.0928 | 58.30% | 3,064,448 B |
开销随装配数量近乎线性扩展,因为每套装配步进一个独立世界,装配之间不共享。单套装配在上方每一条预算线上都从容地落在 10% 以下。
参考帧预算: 60 fps 16.67 ms, 72 fps 13.89 ms, 90 fps 11.11 ms, 120 fps 8.33 ms. 90 fps 这条线是主要的 PCVR 预算。
它是怎么测的
测量方法正是差别所在,所以没有任何一处隐瞒。读完之后,上面的数字该信多少,由你自己判断。
一只真正的 Stopwatch,别无其他
每个数字都来自 Unity EditMode 批处理模式运行,用 Stopwatch 包住解算器自身的 Step 调用。没有渲染、没有输入、没有场景加载。只是纯粹的解算器步进,与整套成本测试早已采用的惯例相同。
中位数的中位数
每一档先跑 5 步预热并丢弃,再跑 20 步计时,公开的数字是把这个窗口独立跑 5 次后的中位数。中位数比平均值更能甩开调度器偶发的一次慢滴答。
内存是算出来的,不是测出来的
内存各列直接由编译后的结构体大小乘以真实的粒子数与约束数得到,所以不带逐次运行的噪声,按构造即为精确。IL2CPP 构建在全部十二档上产出了与编辑器逐字节一致的内存。
特意用一台普通机器
这些是在一台开着普通后台应用(录制或推流、浏览器、聊天或语音)的日常工作机器上测得,而非密封的实验室机器。这是刻意为之。真实买家的机器本就如此。整个窗口内后台 CPU 负载平均约为百分之 4 到 5,此前的空闲运行也已存档以供比较。
我们公开较慢的那个数字
编辑器列在 Mono 下运行托管衔接代码,并开着集合安全检查,这些开销发行版构建会剥除。构建列是在同一窗口内实际运行的 Windows x64 IL2CPP 发行播放器,十二档中的每一档都比它的编辑器对照更快,而不只是持平。帧预算百分比特意采用较慢的编辑器列,所以它是一个保守的上限,发行版构建只会更好。
DOTS 的速度,没有 Entities 的税
Weft 建立在 Burst、C# Job System、Collections 与 Mathematics 这套 DOTS 基础之上,但不使用 ECS,也不带 Entities 依赖。你无需采用 Entities 的项目结构,就能获得 DOTS 级的解算器性能。
性能-质量与设备等级预设
Weft 提供面向买家的预设菜单,把仿真速率、子步数、迭代次数,以及上面的调度器设置绑定到一个具名等级上。选择一个等级,与你自己手动设置这些字段完全等价,不会改变其他任何东西。
两个菜单都位于 Unity 菜单栏的 Weft / Performance Profile。
性能-质量等级
| 等级 | 仿真速率 | 子步数 | 迭代次数 | 调度 | 批处理调度 |
|---|---|---|---|---|---|
| Performance | 60 Hz | 2 | 2 | Concurrent | On |
| Balanced | 60 Hz | 4 | 4 | Auto | Off |
| Cinematic | 60 Hz | 6 | 6 | Auto | Off |
| Crowd | 60 Hz | 4 | 4 | Auto | Off |
设备等级
| 等级 | 仿真速率 | 子步数 | 迭代次数 | 调度 | 批处理调度 |
|---|---|---|---|---|---|
| Desktop | 60 Hz | 4 | 4 | Auto | Off |
| Quest-class mobile XR | 45 Hz | 3 | 3 | Concurrent | On |
两张表中的每个值都是临时的。Quest 级移动 XR 那一行尤其是等待真实设备测量的诚实起点,而非凭眼力调好的最终数字。
Crowd 是唯一开启休眠的等级。稳定下来的服装会完全进入闲置,帧开销接近零,代价是唤醒速度比出货默认值略慢。
任何预设都绝不会触碰自碰撞。关闭它会改变视觉行为,所以它仍是一个需要你为每个组件单独刻意设置的手动旋钮。
Weft 在哪里运行
Weft 是面向你自己的 Unity 应用或游戏的 Unity 软件包。导入它,面向你自己的构建(PC、PC VR,或你的项目已在发行的某个独立平台),它就像任何原生软件包一样嵌入进去。这就是全部受支持的范围,是刻意为之。
实时社交与角色沙盒在加载用户上传时,会在门口剥除自定义的解算器代码。它们以此让不受信任的上传能安全地在别人的客户端上运行,这适用于以这种方式构建的每一个原生解算器,Weft 也不例外。所以那些平台不在范围之内,这是它们工作方式的性质,而非这里的缺陷。
独立 Quest 级 XR
我们还没有在独立头显上测过 Weft。代码能在对应的芯片上运行,所以是有可能的,但有可能不等于已测量。一台头显和一部手机现在已在手,一旦真正测过,数字就会补到这里。在那之前,我们不会公开自己没有实际测过的数字。
确定性
Weft 的回放只有在同一构建跑在同一平台上时才逐位一致。跨不同平台做到逐位一致,目前它还做不到。
这个承诺是同一构建、同一平台、并且同一设置。录制完成后再更改仿真速率、子步数、迭代次数或刚度,都会破坏该录制的逐位回放,这与更改其他任何构建或平台细节的效果一样。
仿真速率也是一个诚实的吞吐量旋钮。以一半的频率运行,也就是用 30 Hz 代替出货默认的 60 Hz,由于解算器步进次数减半,每实际秒的解算器总耗时也大约减半。