mcpField
S
scenario-unity-web

scenario-unity-web

github.com/scenario-labs开发1.2k231 次安装1 天前更新
代码仓库

关于 scenario-unity-web

面向 Unity 6.3 Web 发布的开发技能,指导开发者按托管环境配置构建、压缩、内存与页面互操作。流程要求通过真实主机和浏览器验证加载、字节预算、图形 API 与画面。

主要功能

  1. 01按主机应用 Web 构建设置
  2. 02检查构建体积与压缩响应头
  3. 03配置页面与 Unity 互操作
  4. 04在 Chrome 中验证加载和内存
  5. 05检查启动预算与加载时间

适用场景

  1. 01为网站或门户准备 Unity Web 构建
  2. 02排查压缩或响应头导致的加载问题
  3. 03验证页面与游戏的消息交互
  4. 04测量移动端启动内存和下载预算

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scenario-labs/skills --skill scenario-unity-web

安装后在 Claude Code 中输入/scenario-unity-web确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
critique.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
ut_web.py
scripts/AgentKit/Web/
WebJobs.cs
scripts/AgentKitOptional/Addressables/
WebAddressablesJobs.cs
scripts/AgentKitOptional/Tests/
AgentWeb.EditorTests.asmdef
WebReleasePolicyTests.cs
scripts/WebRuntime/Optional/Addressables/
WebDeferredAddressable.cs
scripts/WebRuntime/Plugins/WebGL/
AgentWebBridge.jslib
scripts/WebRuntime/Scripts/
WebBridge.cs
WebErrorReporter.cs
WebLeaderboard.cs
scripts/WebRuntime/WebGLTemplates/AgentWeb/
index.html

详细介绍

Unity Web(Web 专家)

Web 方面的专家级水准,意味着要在玩家实际获取游戏的环境中评判构建产物:从开始游戏前的字节数、由配置了正确标头的实际主机提供服务,到在真实浏览器中加载,并能报告运行的是哪种图形 API、堆增长了多少,以及页面与游戏是否能通信。原则是:由主机选择压缩方式,预算以首次可玩的时刻为衡量点;只有经提供服务的构建在无头模式下零错误加载成功,并且截图经过检查,才算达标。目标环境:Unity 6000.3.21f1、URP 17.3、macOS 上的 Chrome headless。如果此处提到的同级技能不在你的可用技能中,请让用户安装(npx skills add scenario-labs/skills --skill <name>);无人值守时,根据工具架构继续操作,并标明这一缺口。

必备背景: scenario-unity-expert(渠道、审查循环、6.3 陷阱)。工具包: ut_env、ut_run(包括 build(P, "web")、run_tests)、ut_review,以及此技能的 scripts/ut_web.py、 scripts/AgentKit/Web/WebJobs.cs 和 scripts/WebRuntime/(桥接、.jslib、错误报告器、模板)。

立场(专家补充)

  1. 由托管方决定压缩方式。 自有 HTTPS 服务或 CDN:使用 Brotli,关闭回退;每个文件的 Content-Encoding 单独设置;所有 .wasm* 文件都设置为 application/wasm(6.3 Manual)。纯 HTTP:使用 gzip(观察到 Chrome 在局域网地址拒绝了 Brotli,报错 ERR_CONTENT_DECODING_FAILED;localhost 不受影响)。itch.io:开启 Decompression Fallback(Max O'Didily 8iApGVX--B0 [00:01:40])。Poki:关闭。
  2. 为开始游戏前的下载量设定预算。 CrazyGames 会统计从初始下载到首次触发 gameplayStart 之间的下载量:移动端首页为 20 MB,其他情况为 50 MB,文件数上限为 1,500。延后加载的内容必须在此时刻之后请求(网络日志可证实)。仅为首次可玩时刻所需的资源包添加预加载标签:这会让更多字节计入统计窗口(观察到开始前增加了 0.84 MB)。
  3. 加载时间才是指标;宽带速度足够后,二进制文件和 CPU 就是主要瓶颈。 加载时间缩短 25%,会使会话数增加 50%(Craven,LlE35onVdmQ [00:08:40]);超过 86 Mbps 后,收益趋于平缓 [00:11:26]。使用 CPU 限速和延迟进行测量;托管覆盖率取决于加载时间(Loveridge,FYsVftoLBP8 [00:16:12])。妥善设计等待体验:显示带有操作说明的加载卡片,而不是一条空白进度条(Craven [00:14:16]);然后让玩家点击开始,同时解锁音频。
  4. 一个线程、一个堆、浏览器的时钟。 所有 ThreadPool API 都会导致无法恢复的挂起:应使用 Awaitable、协程和 UnityWebRequest(观察到 Task.Run(...).Result 会冻结标签页)。堆会从 Initial Memory Size 开始增长,增长可能导致手机崩溃:根据实测会话设置 Initial(观察到 32 MB 增长到 68 至 74 MB;设置为 80 后不再增长)。将 targetFrameRate 保持为 -1:Unity 无法查询刷新率(6.3 Manual)。
  5. WebGL 2 已正式发布;WebGPU 用于计算,且会静默回退。 6.3 至 6.5 中为实验功能;从 6.6 起受支持,但需选择启用。保留 WebGL 2 作为回退,并记录 SystemInfo.graphicsDeviceType(观察到纯 HTTP 页面无报错地使用了 WebGL 2)。WebGL 2 的蒙皮在 CPU 上执行(30 个角色:WebGPU 为 30 fps,WebGL 2 为 7 fps;Duncan 3bu4WZUCGYc [~00:15:13]),且只支持非定向光照贴图。
  6. 网页和游戏之间的契约很有限。 .jslib 使用 ES5,字符串以堆指针形式传递,通过 makeDynCall 回复静态 [MonoPInvokeCallback],使用 SendMessage 向名称完全匹配的对象发送一个 JSON 字符串。默认情况下,Unity 会接管整个页面的键盘输入:一个页面名称字段收不到任何输入,直到设置 WebGLInput.captureAllKeyboardInput = false(观察到)。没有系统字体:CJK 和希腊语名称显示为空白,尽管 Font.HasCharacter 显示字符存在(观察到)。门户会忽略或重写 index.html,因此桥接代码应放在 .jslib 中。
  7. 实际发布的内容不一定是你设置的内容。 Strip Engine Code 只会移除资源包实际使用的类(观察到 Could not produce class with ID 182;解决方法:使用 link.xml)。Code Optimization 和纹理子目标设置保存在 Library/ 中:全新克隆会读取 Shorter Build Time(观察到)。Safari 的 iframe 中没有 IndexedDB(6.3 Manual):在 itch.io 上,Safari 玩家可能需要重新加载所有内容。
  8. 按在线服务的方式发布,并删掉不值得占用字节的内容。 使用哈希名称,保留上一版构建,分阶段向 5% 的用户发布(Loveridge [frame 00:23:29]),并为每个版本保留符号文件和错误收集器。“如果它对游戏画面保真度的提升只有百分之一或两个百分点……就该删掉”[00:11:15]:此处 URP 后处理数据占用了 1.61 MB。

首先确认

一次性询问:每个宿主或门户(压缩、回退、页面所有权、iframe);受众和浏览器最低版本(WebAssembly 2023 需要 Safari 16.4+、Chrome 91+、Firefox 89+,而 Unity 支持 iOS Safari 15;CrazyGames 默认在 iOS 上禁用 Unity);从启动到开始游戏的字节数预算,以及在指定线路速度和地区下的秒数;2D 还是 3D、URP、光照贴图、蒙皮人群;计算需求(WebGPU);页面 API 和任何页面文本字段;脚本可使用的玩家文本(字体);桌面和移动端(双 DXT/ASTC 数据);音频(首次点击);Unity 版本。默认值:仅 WebGL 2;自有 HTTPS + Brotli;门户移动端 20 MB,其他情况 30 MB(Loveridge [00:03:29]);Explicitly Thrown;启用 WebAssembly 2023;迭代时使用 Disk Size,发布时使用带 LTO 的 Disk Size;Maximum Memory 2048 MB,Initial 根据测量结果设置;手机 DPR 设为 1;targetFrameRate 为 -1。

工作流

  1. 预检与审计。 ReadSettings、AuditWeb(场景、光照、蒙皮、剥离、启动画面、后处理数据、导入)、ut_web.scan_hang_apis(卡死、targetFrameRate)、scan_jslib、package_report。门槛:审计错误为零;场景列表非空且有效(Cam Ayres bF_eUuxGEcA [00:04:02]);每个高开销包都有合理依据。
  2. 按宿主配置设置。 使用预设(own-https、plain-http、itch、poki、crazygames、dev)调用 WebJobs.ApplySettings,始终传入 code_optimization 和 texture_subtarget;使用 build_target="WebGL" 启动。使用 write_policy 和 WebReleasePolicyTests(EditMode)在 CI 中进行保护。门槛:回读成功,8 项策略测试通过。
  3. 互操作。 ut_web.install_runtime(P);接入 WebBridge、WebLeaderboard、WebErrorReporter(完整代码见流程 P3)。门槛:编译错误为 0,扫描无问题,桥接对象名称与页面调用时使用的名称一致。
  4. 构建。 ut_run.build(P, "web", out=...)。资源包:先运行 WriteBundleLinkXml。门槛:Succeeded;文件集与设置匹配;记录 size_report,并查看 build_log_report(以此处排序,按磁盘上的字节数判断)。
  5. 提供服务并审计标头。 在本地运行 serve 和 header_audit,然后在实际宿主上执行。门槛:错误为零;传输的字节数等于磁盘上的字节数。
  6. 在 Chrome 中加载。 使用页面模拟运行 browser_check(..., metrics_seconds=8, reload=True)。门槛:出现 ready、gameplay_start 和功能事件;横幅为零,意外的控制台错误为零;ready.api 符合预期;开始游戏后才发起延迟请求;移动端设置下堆未增长;帧率稳定;热重载不获取 .data 正文(允许 304);截图已打开。
  7. 预算与加载时间。 运行 budget_check;对加载进行限速测试(20 Mbps、40 ms、CPU x4),并为远距离地区测试 250 ms 的运行。门槛:通过且留有余量。
  8. 变体。 itch(回退、zip、iframe 宿主)、门户 SDK、安全和不安全来源上的 WebGPU、双 DXT/ASTC(merge_texture_variants)、手机模拟(DPR 上限)。每种变体的门槛同第 5 至第 7 步。
  9. 发布。 使用带 LTO 的 Disk Size,归档符号,设置 AGENTWEB_ERROR_URL 或 WebErrorReporter.endpoint,保留上一版构建,制定发布计划(P12)。交接包中注明已验证和假设内容。

数值

数值对应来源
20 / 50 MB,1,500 个文件CrazyGames 首次下载至 gameplayStart 的时间(移动端主页 / 通用场景)CrazyGames
30 MB工作室二进制文件规则(“基本要求”)Loveridge [00:03:29]
+3.6 / +1 / +0.7 MBURP、URP 后处理、TextMeshPro 资源CrazyGames 测试
9.47 MB,8.1 s发布演示构建(LTO):初始下载;在 20 Mbps、40 ms、CPU x4 条件下,至 gameplay_start 的时间实测
+0.83 s同一加载过程,延迟从 40 ms 改为 250 ms实测
-1.61 MB关闭 URP 渲染器后处理数据(从 10.08 MB 降至 8.47 MB)实测
32 至 68-74 MB启动期间默认初始内存大小导致的堆增长;设为 80 MB 时无增长实测
2048 MB最大内存大小;Chrome/Firefox 119 之前,超过此值会出现错误6.3 手册
7 至 30 fps30 个蒙皮角色,WebGL(CPU 蒙皮)与 WebGPU 的对比Duncan [~00:15:13]
48 / 86 Mbps增益趋于平缓时的移动网络 / 宽带中位速度Craven [00:10:53]

更多实测数值:references/expert-notes.md(数值,完整内容)。

质量门槛

  • **可测量:**回读和策略测试通过;审计和扫描无异常;BuildReport 状态为 Succeeded; 在实际主机上 header_audit 显示 0 个错误;browser_check 与预期 API 配合正常;启动后延迟执行; 堆保持平稳;错误会传递至收集器;budget_check 通过;限速加载未超出预算。
  • **视觉:**已打开画布截图:场景已渲染;UI 在 900x500、DPR 1 和 390 px 纵向画布上清晰可读; 所有玩家可输入的脚本各有一行;加载卡片和横幅清晰可读。

常见错误

错误表现修复
用快速本地服务运行压缩构建SyntaxError、“Unable to parse ...framework.js.br”使用 ut_web.serve,或按后缀设置 Content-Encoding
在纯 HTTP 上使用 BrotliERR_CONTENT_DECODING_FAILED使用 HTTPS,或改用 gzip 并允许通过 HTTP 下载
使用 Task.Run、HttpClient、线程、计时器工作始终不会运行;.Result 会冻结标签页使用 Awaitable、协程、UnityWebRequest
“为了移动设备”设置 targetFrameRate = 30Unity 会将自身循环计时所依据的刷新率假定为 60 Hz保持为 -1;仅在有意限帧时进行限制
初始内存设得较小,并在手机上增长启动时堆内存从 32 增至 74 MB;没有连续内存块时发生崩溃初始值 = 实测峰值(heap_advice)
高级剥离 + 资源包Could not produce class with ID,组件缺失使用 WriteBundleLinkXml,然后重新构建
在 CI 上信任 Release 设置全新克隆会读取 Shorter Build Time 和默认纹理格式在每个作业中设置这两项,或提交一个 Build Profile
画布旁的页面字段按键输入被吞掉设置 WebGLInput.captureAllKeyboardInput = false(SetKeyboardCapture)
在任意脚本中显示玩家名称,使用内置字体字形为空;Font.HasCharacter 仍返回 true附带备用字体,或在 HTML 中绘制名称;逐个脚本截图
相信 Graphics API 列表或版本传闻WebGPU 构建运行在 WebGL 2 上;“WebGPU 已在 6.3 中可用于生产环境”按来源记录 API;6.3 到 6.5 为实验性功能,6.6 需选择启用
在 .jslib 中使用 {{{ }}} 或 ES6构建失败使用 ES5,注释中不要使用宏(scan_jslib)
在门户网站的 index.html 中编写页面逻辑CrazyGames 上缺失,在 Poki 上被改写使用 .jslib 或门户网站 SDK
发布模板默认设置Shorter Build Time、Minimal stripping、WASM 2023 关闭:原始 wasm 为 46 MB使用发布预设

交接

  • 接收自 scenario-unity-architecture:不含挂起 API 的代码(扫描结果会反馈);scenario-unity-pipeline-automation:Addressables 布局、CI、Build Profiles(此技能提供策略测试、LZ4、延迟加载、link.xml);scenario-unity-mobile:ASTC 与 DXT、触控、安全区域;scenario-unity-ui:画布在 900x500、DPR 1 和纵向模式下清晰可读,为玩家文本提供备用字体;scenario-unity-rendering-lighting:Web URP 档位(1 到 2 级级联、精简或不使用后处理、非定向光照贴图或实时光照);scenario-unity-shaders 和 scenario-unity-vfx:支持 WebGPU 的计算着色器及 WebGL 2 回退方案;scenario-unity-performance:帧率和内存预算。
  • 交付给 scenario-unity-expert 和用户:按宿主划分的构建文件夹、标头表或服务器配置、size_report、budget_check、browser_check 证据(API、事件、启动前的字节数、堆内存、fps、截图)、策略文件、zip、符号、Verified 和 Assumed 列表。

Unity 6.3 说明

  • 菜单中显示“Web”,代码仍使用 BuildTarget.WebGL、PlayerSettings.WebGL、UNITY_WEBGL、 Assets/WebGLTemplates;6.5 之前没有公开 API 可创建 Build Profile。WebGLInput 位于 UnityEngine.WebGLModule 中,仅在 Web Player 构建中存在:使用 UNITY_WEBGL && !UNITY_EDITOR 对其进行条件编译。
  • URP 模板默认启用 Brotli 和 Shorter Build Time,关闭 WebAssembly 2023,并使用 Minimal stripping(观察所得);WebAssembly 2023 在 6.5 中成为默认选项(Emscripten 4.0.19;6.3 报告为 3.1.39-git)。
  • WebGPU:在 6.3 中处于实验阶段,且仅支持 URP;PSO tracing 和 Microphone 在 6.4 中推出;在 6.6 中获得支持,并提供可选启用、Device Filter 和兼容模式。
  • Build Profile 的纹理压缩设置会覆盖 Player Settings(单个纹理的设置优先级高于两者),并且与 Code Optimization 一样,存储在 ProjectSettings 之外。
  • unityInstance.GetMetricsInfo()(堆内存、fps、卡顿帧)在发布构建中也能使用,无需 Diagnostics Overlay(其 JS 内存读取在 Safari 和 iOS 上显示 N/A);6.3 可通过 IP 对运行中的 Web 构建进行性能分析;Frame Debugger 不适用于 Web。

参考资料

  • references/procedures.md:24 个操作步骤,包含完整代码(含桥接代码)、实时测试和记录结果。
  • references/expert-notes.md:专家评估,包含时间戳、完整数据和意见分歧表。
  • references/critique.md:自我审查标准。
  • references/gui-paths.md:通过窗口和菜单完成相同工作的步骤。
  • references/sources.md:所有来源、凭据、时间戳和修订历史。
  • scripts/ut_web.py、scripts/AgentKit/Web/WebJobs.cs、 scripts/AgentKitOptional/(Addressables 作业、EditMode 策略测试)、scripts/WebRuntime/(桥接代码、错误报告器、.jslib、AgentWeb 模板)。

评论

支持 Markdown