第 39 章 · Quest 与性能预算
这一章解决:第七部的高风险系统放进 Quest 和多人实例后,如何先定预算、再加功能、最后按数据降级。
先看一下
一个世界在 PC 单人测试里能跑,不代表 Quest 多人房也能跑。NPC、对象池、物理对象和同步组件会把 CPU、GPU、内存、网络和 Owner 负载叠在一起。性能预算不是发布前清理,而是设计阶段的边界。
这一章会拿到什么
- 出生点、主区域、最差视角、Quest 构建、多人测试的测量顺序
- 渲染、脚本、网络三类预算清单
- 第七部高风险系统的降级优先级
- 一份上线前性能审计矩阵
依赖前面
- 第 6 章的网络预算
- 第 26 章的轻实时 tick
- 第 32 章的网络拥塞降级顺序
- 第 34 到 38 章的高风险系统边界
这是 difficulty 4 章节。只想先完成最小主项目时,可以先跳到第八部的闭环,再回来看本章的高风险系统。
先测量,再优化
Section titled “先测量,再优化”优化从测量开始。先删模型、先砍脚本、先换 Shader,都可能砍错方向。VRChat 世界要按玩家实际经历的路径测。
| 测量点 | 看什么 |
|---|---|
| 出生点 | 第一眼可见物体、镜子、灯光、音频、视频、NPC 是否过多 |
| 主停留区 | 玩家长时间聊天或战斗时的帧率 |
| 最差视角 | 同时看到最多几何体、透明、粒子、灯光和同步物体的方向 |
| Quest / Android 构建 | 真机帧率、纹理内存、Shader 兼容、发热和卡顿 |
| 真实多人 | 头像、拾取物、音频、视频、网络同步和 Udon 峰值 |
Unity 编辑器的空场景流畅,只能说明基础不坏。真正的预算边界在多人房里出现:头像加载、玩家聚集、同步物体一起动、多个 NPC 同时 tick、音频和特效同时播放。
渲染预算:先看同时可见
Section titled “渲染预算:先看同时可见”Quest 预算里,渲染成本通常先爆。重点不是单个模型,而是同一帧里同时可见的综合成本。
| 成本 | 第七部对应风险 | 常见处理 |
|---|---|---|
| 可见几何体 | 大量 NPC、掉落物、物理碎片 | 分批出现,距离隐藏 |
| 材质数量 | 每个 NPC 多套材质 | 合并材质,复用材质 |
| 纹理内存 | 大量敌人、UI、特效贴图 | 控制尺寸和压缩 |
| 透明与粒子 | 命中、爆炸、技能圈 | 限制同时数量 |
| 灯光和阴影 | 战斗区域动态灯 | 优先烘焙,减少实时灯 |
| 镜子 / 视频 | 社交区叠加战斗区 | 限制视角和开关 |
高风险系统要按「同时可见」预算,而不是按资源总数预算。场景里有 100 个池化敌人并不一定坏,坏的是同一帧里 100 个都 active、都渲染、都跑动画、都同步。
脚本预算:少让对象自己每帧问问题
Section titled “脚本预算:少让对象自己每帧问问题”UdonSharp 性能优化的基本方向是减少大量对象的 Update()。NPC、子弹、掉落物、机关都各自每帧跑逻辑,会把 CPU 切成碎片。
更稳的结构是集中调度。
private void Update(){ if (!Networking.IsOwner(gameObject)) return; if (phase != PHASE_INGAME) return;
double now = Networking.GetServerTimeInSeconds(); if (now - lastNpcTickTime >= npcTickInterval) { lastNpcTickTime = now; TickActiveNpcBatch(); }}对象自身保留事件入口:受击、归还、启用、禁用。持续感知和周期检查交给 Manager 分批处理。这样能控制每帧最多处理多少对象,也方便在 Quest 上把 npcTickInterval 调大。
网络预算:共识字段优先
Section titled “网络预算:共识字段优先”第 6 章已经建立网络预算:同步字段有字节和速率限制,RequestSerialization() 只是请求,网络拥塞时高频装饰事件应该先降级。第七部继续沿用这个顺序。
| 优先级 | 保留 | 可降级 |
|---|---|---|
| 1 | GameState 阶段、分数、波次 | 不降级,只减少字段和发送频率 |
| 2 | PlayerObject 的 HP、Ready、队伍 | 不丢失,必要时降低更新频率 |
| 3 | NPC 关键状态:死亡、目标、阶段 | 只同步关键字段,不同步每帧细节 |
| 4 | 物理对象位置 | 减少数量,转成本地表现或低频重置 |
| 5 | 命中特效、飘字、碎片 | 本地播放或采样发送 |
Networking.IsClogged 可以作为拥塞信号之一。出现拥塞时,停止远端装饰事件,减少非关键对象同步,不要先停掉 GameState 共识字段。共识字段停了,迟入和结算都会坏。
第七部系统的预算边界
Section titled “第七部系统的预算边界”把前几章合在一起,可以得到一张预算表。
| 系统 | 预算指标 | 降级入口 |
|---|---|---|
| NPC | active 数量、AI tick 频率、目标搜索频率 | local-only、分批 tick、减少同步字段 |
| 对象池 | 最大同时 active 数量、池耗尽次数 | 拒绝生成、延迟生成、复用纯视觉对象 |
| 物理对象 | active Rigidbody 数、Owner 切换次数 | 改成本地特效、低频状态、重置点 |
| 对象同步工具 | 同步对象数、组件成本、维护状态 | 回退官方组件、减少同步范围 |
| Quest 渲染 | 最差视角帧率、透明和粒子数量 | 分区、隐藏、降低特效密度 |
这张表适合放进项目 ADR。每加一个高风险系统,就填一次:最大同时 active 是多少,Owner 是谁,迟入怎么恢复,Quest 上怎么降级。
什么时候别支持 Quest
Section titled “什么时候别支持 Quest”这句话需要谨慎,但要能说出来。有些世界的核心体验就是高密度视觉、复杂物理、大量 NPC 或 PC-only Shader。如果把它强行压到 Quest,会把核心体验一起压掉。
判断方式是:Quest 降级版是否还能保留世界承诺。如果合作防守世界在 Quest 上只能保留 3 个敌人、无特效、无物理、无镜子,但核心仍然是多人防守,那可以做。如果某个世界的核心就是大规模实时物理装置,Quest 版只剩空房间,那应该明确做 PC-only,或者把 Quest 版设计成不同玩法。
重点是早判断。不要在项目末尾才发现 Quest 版跑不动。
挑一条试。
- 给合作防守原型写一张预算表:同屏最多几个敌人、几个物理物体、几组粒子?如果 Quest 掉帧,先砍哪一项?
- 把 NPC tick 从 0.2 秒改成 0.5 秒。玩家能感知到的变化是什么?网络和 CPU 有什么变化?
| 场景 | 预期 | 实际 |
|---|---|---|
| 1. 出生点静止 30 秒 | 无明显掉帧,常驻特效和镜子成本可控 | … |
| 2. 主战斗区 4 人 + NPC | 帧率、Udon 时间和同步状态稳定 | … |
| 3. 最差视角 | 同时可见成本在预算内,不出现明显卡顿 | … |
| 4. Quest 真机测试 | Shader、纹理、特效和脚本都能运行 | … |
| 5. 网络拥塞模拟 | 装饰事件先降级,GameState 共识字段保留 | … |
| 6. 池耗尽 | 生成系统拒绝或延迟,不创建额外对象 | … |
- 能按出生点、主区域、最差视角、Quest 构建、真实多人测试性能
- 能区分渲染预算、脚本预算和网络预算
- 能说明为什么大量
Update()会拖垮 Quest - 能按优先级保留共识字段、降级装饰反馈
- 能给每个高风险系统写出一个降级入口
- VRChat Creator Docs · Network Specs and Tips — 同步预算、拥塞和
OnPostSerialization边界。 - VR Creators · VRChat Optimization Guide(访问日期:2026-06-17)— 世界优化测量顺序与 Quest 预算建议。
- UhiyamaLab · Performance Optimization: Reducing Update Calls and Network Load(访问日期:2026-06-17)— 减少
Update()、对象池和网络负载的社区经验。 - 第 32 章 · 修正、插值与优雅降级 — 拥塞时的降级顺序。