@microi.net/cli 4.9.3 → 4.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.codebuddy-plugin/marketplace.json +2 -2
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.workbuddy-plugin/marketplace.json +2 -2
  5. package/.workbuddy-plugin/plugin.json +1 -1
  6. package/assets/build-meta.json +5 -5
  7. package/package.json +1 -1
  8. package/scripts/mcp-server.js +92 -92
  9. package/scripts/microi-cli.js +25 -25
  10. package/scripts/microi-skills.meta.json +157 -130
  11. package/skills/.microi-skills-version.json +2 -2
  12. package/skills/README.md +3 -1
  13. package/skills/app-store/SKILL.md +10 -2
  14. package/skills/microi-ai-application/SKILL.md +1 -1
  15. package/skills/microi-docs-coverage/references/capability-map.md +4 -1
  16. package/skills/microi-form-engine/SKILL.md +6 -3
  17. package/skills/microi-form-layout/SKILL.md +18 -5
  18. package/skills/microi-microservice/SKILL.md +1 -1
  19. package/skills/microi-system-delivery/SKILL.md +5 -2
  20. package/skills/print-engine/SKILL.md +5 -4
  21. package/skills/unity-integration/SKILL.md +151 -0
  22. package/skills/unity-integration/agents/openai.yaml +4 -0
  23. package/skills/unity-integration/references/ai-app-delivery.md +98 -0
  24. package/skills/unity-integration/references/sdk-api.md +82 -0
  25. package/skills/unity-integration/references/toolbox-migration.md +66 -0
  26. package/skills/unity-integration/references/webgl-hosting.md +57 -0
  27. package/skills/v8-frontend-events/SKILL.md +11 -7
  28. package/skills/v8-frontend-events/references/bluetooth-print-api.md +31 -3
  29. package/skills/v8-frontend-events/references/bluetooth-print.md +54 -12
  30. package/skills/v8-mq-mqtt/SKILL.md +140 -52
  31. package/skills/v8-mq-mqtt/references/mqtt-production.md +341 -0
  32. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +205 -0
  33. package/skills/v8-utilities/references/client-api-index.md +4 -2
  34. package/skills/workspace-conventions/SKILL.md +3 -2
@@ -143,10 +143,11 @@ Q1: 核心可见字段数、子表和强任务域?
143
143
  "Name": "MrpGroup",
144
144
  "Label": "MRP 运算",
145
145
  "Component": "CollapseGroup",
146
- "Type": "varchar(50)",
146
+ "Type": "",
147
147
  "Sort": 120,
148
148
  "Visible": 1,
149
149
  "AppVisible": 1,
150
+ "FormWidth": 24,
150
151
  "Config": "{\"CollapseGroup\":{...}}"
151
152
  }
152
153
 
@@ -164,6 +165,10 @@ Q1: 核心可见字段数、子表和强任务域?
164
165
 
165
166
  **作用范围**:从该 CollapseGroup 字段开始,到下一个 `Component in (Tabs, CollapseGroup, Divider)` 字段为止。
166
167
 
168
+ **默认值硬规则**:`CollapseGroup` 必须保存 `FormWidth=24`(PC 表单 100% 宽度);
169
+ `Config.CollapseGroup.ShowFieldCount` 省略时必须补为 `true`。只有用户明确要求隐藏数量时
170
+ 才允许写 `ShowFieldCount=false`,只有用户明确要求非整行实验布局时才允许覆盖宽度。
171
+
167
172
  **与 Tab 的关键区别**:所有 CollapseGroup 标题**始终可见**,分组内字段**默认展开**或**默认收起**,但所有分组的字段**都在同一页面**,可同时展开多个。
168
173
 
169
174
  ### 3.4 控件视觉对比
@@ -223,6 +228,7 @@ V8 事件中可用 `V8.HideFormTab('tabId')` / `V8.ShowFormTab('tabId')` / `V8.C
223
228
  - 字段数 13~30 的表单,必须有可见的**业务分组**(Tab 或 CollapseGroup 二选一),不能让用户上下滚动 5 屏找字段。
224
229
  - 创建 CollapseGroup 分组时,必须设置 `Icon`(如 `fas fa-calculator` / `fas fa-info-circle`),不要默认空白。
225
230
  - 任何 Tab / CollapseGroup 都必须有 `Description` 解释分组用途,不要只放一个标题。
231
+ - 每个 CollapseGroup 必须回读到 `FormWidth=24`;`Config.CollapseGroup.ShowFieldCount` 默认必须为 `true`。
226
232
  - 修改 `diy_table.Tabs` 或 `diy_field.Tab` / `Config.CollapseGroup` / `Config.FieldTabs` 后,必须调用 `microi_refresh_schema_cache`。
227
233
  - Tab 内嵌套 CollapseGroup 时,CollapseGroup 必须设 `DefaultCollapsed=true`(默认收起),避免 Tab 内继续被折叠分组抢首屏空间。
228
234
  - 新增布局节点后必须同时回读 `diy_field` 元数据和目标业务表结构,确认没有新增物理业务列;若当前工具不提供仅元数据能力,只报告设计建议,不得绕过后端直接写表。
@@ -233,7 +239,7 @@ V8 事件中可用 `V8.HideFormTab('tabId')` / `V8.ShowFormTab('tabId')` / `V8.C
233
239
  - ❌ **禁止**仅凭 13~30 个原始字段决定平铺或分 Tab;总有效行超过 6 且存在明确业务域时,至少使用 CollapseGroup 分组。
234
240
  - ❌ **禁止**为 8~10 字段的简单业务表创建多层 Tab 嵌套(直接用 CollapseGroup 即可)。
235
241
  - ❌ **禁止**在用户没有要求时使用 `Tabs` 字段控件(`diy_field.Component='Tabs'`),更优先用 `diy_table.Tabs`。
236
- - ❌ **禁止**为 `Tabs` / `CollapseGroup` / `Divider` / `Alert` 等布局控件设置 `FormWidth=24`,这些控件天然占整行。
242
+ - ❌ **禁止**让 `CollapseGroup.FormWidth` 为空或依赖表默认列宽;CollapseGroup 默认必须显式保存 `FormWidth=24`。Tabs / Divider / Alert 继续按各自运行时规范处理。
237
243
  - ❌ **禁止**只创建 Tab 不写字段的 `Tab` 归属(每个 Tab 必须有至少 1 个非空 `Tab` 的字段)。
238
244
  - ❌ **禁止**用 Tabs 控件的 `FieldCount` 跨过 CollapseGroup 或 Divider 计数(不同布局控件的计数是隔离的)。
239
245
  - ❌ **禁止**把高频访问的字段(如单据编号、项目名称)放进默认收起的 CollapseGroup。
@@ -244,6 +250,7 @@ V8 事件中可用 `V8.HideFormTab('tabId')` / `V8.ShowFormTab('tabId')` / `V8.C
244
250
  修改或新建表单布局后,AI 必须按以下顺序验收:
245
251
 
246
252
  1. **回读字段**:`microi_get_field_list` 检查 `Tab` / `Component` / `Config` 与设计一致。
253
+ CollapseGroup 还必须检查 `FormWidth=24`、`Config.CollapseGroup.ShowFieldCount=true`(除非用户明确覆盖)。
247
254
  2. **回读表与结构**:`microi_get_table_data _SelectFields=['Id'] _PageSize=1` 验证表可读,并检查实时表结构未因纯布局节点新增物理业务列。
248
255
  3. **清缓存**:`microi_refresh_schema_cache tables=['表名']`。
249
256
  4. **手动打开表单**:通过 Playwright 或 V8 引擎调用,截图第一屏。
@@ -253,6 +260,10 @@ V8 事件中可用 `V8.HideFormTab('tabId')` / `V8.ShowFormTab('tabId')` / `V8.C
253
260
  - 没有任何"只剩 1 个字段的 Tab"。
254
261
  6. **业务闭环**:新建一条测试数据、编辑、查看、删除,验证字段在正确分组中显示。
255
262
 
263
+ 若“表单设计器能看到、真实新增/编辑/查看表单看不到”,必须先读取表级 `InFormV8`
264
+ 以及相关字段 V8,搜索 `V8.FieldSet`、`hideField`、`Visible=false`、`HideFields`。设计模式
265
+ 通常跳过这些运行态事件;未完成这一步不得直接判定为 Microi.Client 渲染缺陷。
266
+
256
267
  ## 7. 反例参考(必须避免)
257
268
 
258
269
  ### 反例 1:MRP 运算 3 字段单独建 Tab
@@ -328,11 +339,10 @@ microi_update_table({
328
339
 
329
340
  ```js
330
341
  // 1. 创建一个 CollapseGroup 字段
331
- microi_add_field({
342
+ microi_add_layout_field({
332
343
  tableId: "01KTASHWEBE514R1XTB0WVJJRX",
333
344
  name: "MrpGroup",
334
345
  label: "MRP 运算",
335
- type: "varchar(50)",
336
346
  component: "CollapseGroup",
337
347
  sort: 150,
338
348
  visible: 1,
@@ -346,9 +356,12 @@ microi_add_field({
346
356
  Theme: "primary",
347
357
  ShowFieldCount: true
348
358
  }
349
- })
359
+ }),
360
+ confirmExecution: "MrpGroup"
350
361
  })
351
362
 
363
+ // 工具默认写入 FormWidth=24;回读必须确认宽度为 24 且 ShowFieldCount=true。
364
+
352
365
  // 2. 让"MRP 运算"相关字段归属到该 CollapseGroup
353
366
  // 范围方式:把 CalcStatus、CalcBatchNo、MrpTime 三个字段的 Sort 排在 150~300 之间,
354
367
  // 下一个 CollapseGroup/Tabs/Divider 字段之前的所有字段都属于该分组
@@ -67,7 +67,7 @@ src/
67
67
  AppKey 稳定且只含安全字符。`microi.routes.json` 是页面事实源,删除/新增路由后由
68
68
  发布流程同步 `sys_microiservice_page`,不要从 Vue 源码猜路由。
69
69
 
70
- 本地项目必须位于当前连接对应的 `Microi-V8-Engine/{系统名称} ({ApiBase域名})/{OsClient}.{OsClientType}.{OsClientNetwork}/AI应用/{appKey}`。`microi.apps/` 是官方应用商城发行包工程目录,不是 MicroService 源码目录;发行包只能引用、构建或快照当前租户的唯一源码,不得在包内嵌套第二份可编辑 `microservice/` 工程。
70
+ 本地项目必须位于当前连接对应的 `Microi-V8-Engine/{系统名称} ({ApiBase域名})/{OsClient}.{OsClientType}.{OsClientNetwork}/AI应用/{appKey}`。该应用目录同时承载 MicroService 源码、Manifest、接口引擎、资源策略、测试和应用商城上传素材,是唯一事实源;禁止创建平行的 `microi.apps/` 发行根,也不得在应用内嵌套第二份可编辑 `microservice/` 工程。
71
71
 
72
72
  构建前遵守本地 OOM 保护;已有 dev server 可复用时不重复启动。新脚手架必须支持独立
73
73
  访问时的平台帐号登录,但独立 Vite 预览仍没有菜单/弹窗等完整宿主上下文,不能替代宿主验收。
@@ -99,12 +99,12 @@ Detail/Edit 自定义表单,不能用它关闭 List/Card 展示设计。
99
99
  - ❌ **禁止**为 ≤7 字段的业务域单独建 Tab(必须改用 `CollapseGroup`,否则用户必须点击 Tab 才能看到 3~5 个字段,违反"首屏信息密度"原则)。
100
100
  - ❌ **禁止**为 13~30 字段的表把所有字段平铺(必须用 Tab 或 CollapseGroup 分组)。
101
101
  - ❌ **禁止**在用户没有要求时使用 `Component='Tabs'` 字段级控件(更优先用 `diy_table.Tabs` 表级 Tab)。
102
- - ❌ **禁止**为 Tabs / CollapseGroup / Divider / Alert 等布局控件设置 `FormWidth=24`(这些控件天然占整行)。
102
+ - ❌ **禁止**让 CollapseGroup 依赖空 `FormWidth`;CollapseGroup 默认必须显式保存 `FormWidth=24`,并默认设置 `Config.CollapseGroup.ShowFieldCount=true`。Tabs / Divider / Alert 按各自运行时规范处理。
103
103
  - ❌ **禁止**只创建 Tab 不写字段的 `Tab` 归属(每个 Tab 必须有至少 1 个非空 `Tab` 的字段)。
104
104
 
105
105
  典型反例:`yutaoliaojieguo` 表 13 字段有"MRP 运算"3 字段 Tab — 这是错误的,应该用 `CollapseGroup` 把 MRP 3 字段收起(默认展开),让用户第一屏看到基础信息 + MRP 字段而不是必须点击 Tab 切换。详见 `microi-form-layout/SKILL.md` 的"反例参考"章节。
106
106
 
107
- 表单控件选择必须参考 `Microi.Client/src/views/form-engine/diy-field-component/diy-component-list.json`,包括文本、数字、日期、选择、树、部门、地址、关联表单、弹窗选表、子表、上传、富文本、代码、地图、二维码、布局控件等;普通字段不手动设置 `FormWidth`,整行控件才设 `24`。
107
+ 表单控件选择必须参考 `Microi.Client/src/views/form-engine/diy-field-component/diy-component-list.json`,包括文本、数字、日期、选择、树、部门、地址、关联表单、弹窗选表、子表、上传、富文本、代码、地图、二维码、布局控件等;普通字段不手动设置 `FormWidth`,整行控件才设 `24`。CollapseGroup 必须显式设 `24`,并默认开启 `ShowFieldCount`。
108
108
 
109
109
  ### 3. 主子表与关联表单设计
110
110
 
@@ -124,6 +124,9 @@ Detail/Edit 自定义表单,不能用它关闭 List/Card 展示设计。
124
124
  关系语义审查。MCP 会硬性拒绝“1:N + JoinForm”、自关联 JoinForm、缺主/子外键、缺
125
125
  `Display=0/AppDisplay=0/HasChild=0` 隐藏子菜单或缺 `(OsClient, FK)` 回查索引;AI
126
126
  不得改用直接单字段工具绕过。
127
+ - 复用已有子表时,优先复用源 `TableChild` 已验证、当前用户有权限的子表菜单;只有不存在
128
+ 可复用菜单时才新建隐藏菜单。设计器显示但运行表单不显示时,必须先检查主表 `InFormV8`
129
+ 是否通过 `V8.FieldSet`/`hideField` 把目标 TableChild 设为不可见。
127
130
 
128
131
  `JoinForm` 的可移植 Manifest 只写名称,不写租户 Id:
129
132
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: print-engine
3
- description: 生成和审查 Microi 打印引擎 Print Engine 模板 JSON。用于创建 mic_print 模板、PageObj 布局、PrintObj 数据绑定、可打印报告、标签或合同。
3
+ description: 生成和审查 Microi 打印引擎 Print Engine 模板 JSON。用于创建 mic_print 模板、PageObj 布局、PrintObj 数据绑定、可打印报告、标签或合同;蓝牙 TSPL/CPCL/ESC-POS、GP-M322 或 CC4 需求转交 v8-frontend-events 蓝牙参考。
4
4
  ---
5
5
 
6
6
  > **Codex 强制前置:** 当前宿主为 Codex 时,在使用本 Skill 前必须先完整读取 `../microi-codex-installer/SKILL.md`,完成“Codex 每任务最新版硬门禁”;门禁未通过不得继续本 Skill。非 Codex 宿主跳过此项。
@@ -19,14 +19,15 @@ description: 生成和审查 Microi 打印引擎 Print Engine 模板 JSON。用
19
19
  ## 与蓝牙直连打印的边界
20
20
 
21
21
  本 Skill 负责 `mic_print`、`PageObj`、`PrintObj`、浏览器预览和模板化纸张输出。
22
- 如果需求明确是蓝牙标签机/小票机、TSC/TSPL、ESC/POS
22
+ 如果需求明确是蓝牙标签机/小票机、TSC/TSPL、CPCL、ESC/POS、佳博 GP-M322、
23
+ ZICOX CC4、BLE/SPP 或
23
24
  `V8.Print.prepareSend`,应同时读取
24
25
  `../v8-frontend-events/references/bluetooth-print.md`:
25
26
 
26
27
  - Print Engine 决定“页面/模板如何排版”,适合 A4、PDF、浏览器打印和统一模板。
27
- - `V8.Print` 生成打印机原生命令并通过 BLE 写特征,适合标签和热敏小票。
28
+ - `V8.Print` 生成/适配打印机原生命令并通过 BLE 或 Android SPP 写入,适合标签和热敏小票;GP-M322 保持 TSPL 原字节,CC4 可自动生成 CPCL。
28
29
  - 两者可以由同一个按钮按设备能力选择,但不能把 `PageObj` 直接交给
29
- `V8.Print.prepareSend`,也不能把 TSC/ESC 字节当作 Print Engine JSON。
30
+ `V8.Print.prepareSend`,也不能把 TSPL/CPCL/ESC-POS 字节当作 Print Engine JSON。
30
31
 
31
32
  ## 数据模型
32
33
 
@@ -0,0 +1,151 @@
1
+ ---
2
+ name: unity-integration
3
+ description: Microi吾码 Unity、UPM SDK、WebGL、3D 游戏/数字孪生、DiyToken/V8 通讯、AI 应用商城交付与完整验收规范。用于评估或提取 Unity 工具箱,创建 Microi.Unity 包,开发 WebGL 场景,接入 Microi.Client 宿主与 V8 接口,引入可授权素材,发布可安装 AI 应用,或审查 Unity 代码是否错误进入 Microi.Server。
4
+ ---
5
+
6
+ > **Codex 强制前置:** 当前宿主为 Codex 时,在使用本 Skill 前必须先完整读取 `../microi-codex-installer/SKILL.md`,完成“Codex 每任务最新版硬门禁”;门禁未通过不得继续本 Skill。非 Codex 宿主跳过此项。
7
+
8
+ # Microi Unity 完整交付
9
+
10
+ 目标不是“做出一个 Unity 工程”,而是交付一条可复用、可安装、可升级、可验证的 Microi 3D 应用链。
11
+
12
+ ## 按任务读取参考
13
+
14
+ | 当前任务 | 必须读取 |
15
+ |---|---|
16
+ | 新建或调用 `Microi.Unity` | `references/sdk-api.md` |
17
+ | WebGL 模板、Microi.Client/AI 应用宿主、性能与部署 | `references/webgl-hosting.md` |
18
+ | AI 应用源码、商城包、官方发布与安装回读 | `references/ai-app-delivery.md` |
19
+ | 从已有客户项目提取 Unity 工具箱或素材 | `references/toolbox-migration.md` |
20
+
21
+ 若任务横跨多项,逐个读取相应参考,不从文件名猜协议。
22
+
23
+ ## 先做架构裁决
24
+
25
+ 1. Unity 客户端 SDK 使用仓库根级 UPM 包:`Microi.Unity/package.json`。
26
+ 2. `UnityEngine`、`UnityWebRequest`、Editor API 和 `.jslib` 不进入 `Microi.Server` 的 .NET 类库。
27
+ 3. 玩家进度、设备状态、任务、积分和交互记录优先由 V8 接口引擎编排。
28
+ 4. 只有缺失的平台级可信协议、鉴权、密钥隔离或底层原子能力,才允许修改 `Microi.Server`;修改前必须说明 V8 为什么无法完成。
29
+ 5. 实时房间、租约、进度和去重事实必须按 `OsClient` 存入共享数据库、Redis 或可靠消息系统,不能用单节点内存字典当事实源。
30
+
31
+ 推荐目录:
32
+
33
+ ```text
34
+ Microi.Unity/ 公共 UPM SDK
35
+ ├─ Runtime/Api/ UnityWebRequest 与 DosResult
36
+ ├─ Runtime/WebGL/ C# 浏览器桥
37
+ │ └─ Plugins/WebGL/*.jslib
38
+ ├─ Editor/ 通用构建工具
39
+ └─ Samples~/ 可运行最小示例
40
+
41
+ AI-Project/<project>/Unity/ 具体 Unity 工程与场景
42
+ Microi-V8-Engine/.../AI应用/<appKey>/ 唯一 AI 应用源码与商城资源
43
+ microi.doc/docs/doc/system-engine/ 官方长期文档
44
+ ```
45
+
46
+ ## 标准工作流
47
+
48
+ ### 1. 发现与盘点
49
+
50
+ - 读取 Unity 版本、渲染管线、`Packages/manifest.json`、场景、Editor、Runtime、WebGL Plugins 和现有构建脚本。
51
+ - 搜索 Microi.Client 已有 Unity 宿主、现有 V8 Key、官方 AI 应用是否重名。
52
+ - 为模型、动作、贴图、字体、音频逐项记录来源、作者、许可证、版本和是否允许再分发。
53
+ - 在启动 Unity、Node、浏览器或构建前检查物理内存、同类进程、端口与任务归属。
54
+
55
+ ### 2. 分离公共能力与业务能力
56
+
57
+ - API 客户端、DosResult、上下文注入、Token 轮换、浏览器事件和通用构建工具进入 UPM。
58
+ - 相机路径、触发区、特定场景模型、关卡、客户设备协议与业务脚本留在具体项目。
59
+ - 首次提取采用复制和重构;新包完成引用替换与回归前,不移动或删除旧项目文件。
60
+ - 公共包必须有 `package.json`、asmdef、README、LICENSE、CHANGELOG 与 Sample。
61
+
62
+ ### 3. 建立 WebGL 宿主握手
63
+
64
+ - Unity 就绪后由宿主用 `SendMessage` 注入 `ApiBaseUrl/OsClient/Authorization/Did`。
65
+ - 会话只保存在运行时内存;禁止 Token 进入 URL、场景、Prefab、日志、构建产物或版本库。
66
+ - `.jslib` 只提供稳定事件:ready、authorization rotated、business event。
67
+ - Token 轮换回调同时携带发起请求时的旧 Token;宿主先做迟到响应保护,再更新统一会话。
68
+ - 页面离屏暂停;组件卸载调用 Unity `Quit()`,清理 iframe/Canvas、WASM、WebGL 上下文、监听器与全局回调。
69
+
70
+ ### 4. 用 V8 设计服务端
71
+
72
+ ```text
73
+ POST {ApiBase}/apiengine/{ApiEngineKey}
74
+ Content-Type: application/json
75
+ osclient: {OsClient}
76
+ apiengine: 1
77
+ authorization: Bearer {DiyToken}
78
+ did: {DeviceId}
79
+ ```
80
+
81
+ - 身份只取 `V8.CurrentUser`;禁止相信客户端 UserId、角色、部门或权限结论。
82
+ - 重新校验坐标、数量、字符串长度、状态转换和资源归属。
83
+ - 写接口使用稳定 `RequestId/EventId` + 数据库唯一索引/幂等台账;锁不能替代幂等。
84
+ - 匿名多人由服务端签发 `SessionId + SessionSecret`;数据库只保存秘密哈希,公开快照不得返回秘密、UserId、设备指纹或内部权限字段。
85
+ - 在线角色、房间版本和掉线到期时间进入共享数据库/Redis;客户端心跳、接口重试和节点切换都不能依赖进程内字典。
86
+ - 位置心跳由服务端限制地图边界、最大速度和递增序列;过期查询以服务端时间为准,正常离场与租约超时都必须幂等。
87
+ - 公屏文字限制长度、频率、表情白名单与稳定请求 ID;DOM 输入框阻止键盘事件冒泡,避免聊天时角色继续移动。
88
+ - 接口引擎 `Code=1` 自动提交,失败返回其它 Code 自动回滚,不手动 Commit/Rollback。
89
+ - 表、索引、菜单、接口与权限通过应用 Manifest 安装,不为游戏资源新增 `Microi.Upgrade` 定制迁移。
90
+ - 所有接口必须声明 `ResourcePolicies.ApiEngines`:官方核心 `Managed`;租户扩展 `CreateIfMissing`,后续升级不覆盖。
91
+
92
+ ### 5. 构建可安装 AI 应用
93
+
94
+ - `ApplicationType` 使用 `Web`;Vue 3 + Vite + TypeScript 作为页面外壳,Unity Canvas/WebGL 与普通 DOM 分层。
95
+ - 官方租户的 `AI应用/<appKey>` 是私有源码、构建脚本、V8、Manifest 与商城合约的唯一编辑根。
96
+ - 页面必须 poster-first:未启动时不下载大体积 WASM/Data;提供加载、错误、重试、全屏、退出和低性能提示。
97
+ - 多人界面要显示本地及远端昵称;同模型远端角色使用快照插值,失效租约及时销毁;公屏固定在不遮挡核心操作区的位置并支持键盘与表情选择。
98
+ - 构建门禁必须拒绝缺失 Unity 产物的“空壳发布”,并校验 WASM、Data、体积、哈希、本机地址、source map 与疑似硬编码 Token。
99
+ - 先同步私有源码,再发布不可变 Web 产物,最后生成/发布商城包;三个动作分别回读。
100
+
101
+ ### 6. 补齐官网与 Skill
102
+
103
+ - 长期能力在中文官网“系统引擎”下建立独立页面,并加入 `mapping_zh.json`、视觉画像与文档责任映射。
104
+ - 页面优先使用主视觉、架构卡、步骤卡和折叠技术细节;不要用连续大段文字堆满屏幕。
105
+ - 不手工维护 `microi.doc/docs/en/`,不因普通功能文档修改 `about/update-log.md`。
106
+ - 文档至少覆盖:架构边界、UPM 安装、宿主握手、V8 请求、安全、CORS、构建、部署、商城安装和分层验收。
107
+
108
+ ## 资产与视觉红线
109
+
110
+ - AI 生成素材保存逐图提示词、生成时间、用途和源文件;不要只提交最终图片。
111
+ - AI 设定图、渲染目标图与真实 Unity 运行截图必须分开标注;未通过实机近景、拓扑、材质、性能验收时禁止宣称“与设定图一模一样”或“商业 AAA 已达成”。
112
+ - 网络素材必须允许商业使用和再分发;许可证不清晰就改用原创、程序化或明确授权素材。
113
+ - 官方包不携带客户专属场景、品牌秘密、私有协议或无法追溯的二进制模型。
114
+ - “超清”不能只靠大纹理:同时控制材质、光照、阴影、LOD、裁剪、像素比和下载体积。
115
+ - 支持浅/深色外壳、键盘焦点、减少动效偏好、响应式安全区与清晰错误状态。
116
+
117
+ ## WebGL 质量基线
118
+
119
+ - 使用仓库已验证的 Unity LTS;WebGL 采用兼容的 Built-in 或 URP,不走 HDRP。
120
+ - 校验 WebGL 2、WASM、正确 MIME、gzip/Brotli 响应头或解压回退、高 DPI 上限、全屏、键鼠/手柄、焦点恢复和退出释放。
121
+ - WebGL 必须经 HTTP(S) 验收,不能用 `file://`。
122
+ - Unity 2022.3 不把移动浏览器描述为官方支持;移动端需要独立触控、内存、画质和弱网测试。
123
+ - 程序化创建、反射或字符串类型名先用 `link.xml` 精确保留;若 WebGL 仍报告原生 `class ID` 被裁剪,可对该构建关闭 `PlayerSettings.stripEngineCode`,但必须复核包体和浏览器控制台。
124
+ - WebGL 模板设置 `autoSyncPersistentDataPath: true`,并把弃用警告也纳入控制台验收。
125
+ - 同一次高资源阶段只运行一个 Unity/Node/浏览器重任务,并遵守工作区 OOM 保护。
126
+
127
+ ## 分层验收矩阵
128
+
129
+ | 证据层 | 必须断言 |
130
+ |---|---|
131
+ | 源码 | UPM 可解析、C# 编译、V8/Manifest/策略测试、安全扫描 |
132
+ | Unity Editor | Play、移动、奔跑、跳跃、碰撞、交互、暂停恢复 |
133
+ | WebGL | IL2CPP/WASM 构建成功,Loader/Data/WASM 完整 |
134
+ | 浏览器 | HTTP 加载、全屏、输入、控制台、DPR、退出释放 |
135
+ | Microi 租户 | 当前用户隔离、Token 轮换、保存重放、无权失败 |
136
+ | 多人在线 | 至少两个独立会话互见唯一昵称、移动与动作;异常断线超过租约后双方快照均不再返回该角色 |
137
+ | 实时公屏 | 两个独立会话互相收发文字与表情;非法表情、超长、超频和请求重放均被正确处理 |
138
+ | 多节点 | 重复投递、节点切换、失败恢复时副作用仅一次 |
139
+ | AI 应用 | 私有源码回读、运行版本哈希、列表/详情公开可见 |
140
+ | 应用商城 | 包版本/策略回读,非官方租户安装与升级通过 |
141
+
142
+ 任何未执行层都要明确写成未验证或受阻。应用受理编号、源码测试或本地构建不能替代公开 URL、真实租户和非官方安装证据。
143
+
144
+ ## 停止发布的条件
145
+
146
+ - Unity 许可证未激活或 WebGL 模块缺失。
147
+ - Unity 构建只有外壳,没有真实 WASM/Data。
148
+ - 素材许可证、AI 提示词或资产来源不可追溯。
149
+ - 正式产物出现本机地址、Token、source map 或超限单文件。
150
+ - 官方应用重名、目标版本不明确、远端源码/运行版本基线未回读。
151
+ - 商城包缺少 `ResourcePolicies.ApiEngines`,或把租户 Hook 错设为 `Managed`。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Microi Unity 集成"
3
+ short_description: "交付 Unity UPM、WebGL、V8 与可安装 AI 应用"
4
+ default_prompt: "使用 $unity-integration 设计、实现并分层验收完整的 Microi Unity WebGL 应用。"
@@ -0,0 +1,98 @@
1
+ # Unity AI 应用与商城交付
2
+
3
+ ## 唯一源码
4
+
5
+ 官方 AI 应用源码放在当前官方连接对应的:
6
+
7
+ ```text
8
+ Microi-V8-Engine/<connection>/<product>/AI应用/<appKey>/
9
+ ```
10
+
11
+ 同一应用的 Vue 外壳、Unity 构建接入、V8 源码、Manifest、资源策略、测试和发布合约都从这里生成。Unity 工程可以保留服务端镜像,但必须由唯一源码生成并做一致性检查。
12
+
13
+ 最小文件:
14
+
15
+ ```text
16
+ .microi-micro-app.json
17
+ app.json
18
+ package.json
19
+ microi.routes.json
20
+ package-contract.json
21
+ resource-policies.json
22
+ system.manifest.json
23
+ src/
24
+ public/
25
+ server/engines/
26
+ scripts/
27
+ tests/
28
+ ```
29
+
30
+ ## Web 外壳
31
+
32
+ - Vue 3 + Vite + TypeScript。
33
+ - 复用工作区标准 `microi.v8.js` 与 `microi-ai-app-auth.js`,不要复制改造出第二套认证协议。
34
+ - 匿名模式可以承载公开多人玩法,但必须使用服务端签发、只存哈希、可过期的会话秘密;个人持久化接口仍要求 DiyToken。
35
+ - `ApplicationType=Web`,独立入口为 `index.html`。
36
+ - 构建状态明确区分 `available` 与 `publishable`;无真实 Unity WASM/Data 时禁止正式发布。
37
+ - WebGL 公屏优先使用可访问的 DOM 输入控件并拦截键盘传播;Windows 可使用原生 UI/UIToolkit。不要在外壳和 Unity 中重复绘制同一组操作提示。
38
+
39
+ ## 多人租约与公屏交付
40
+
41
+ - 在线角色的事实源使用按 `OsClient` 隔离的共享数据库/Redis,不能使用 API 节点静态字典;客户端心跳周期必须短于租约超时。
42
+ - 加入响应只向本人返回会话秘密;数据库保存 SHA-256,位置快照只公开昵称、受限坐标、朝向、动作与房间版本。
43
+ - 正常卸载/离开主动调用 leave;浏览器崩溃、断网或 `kill -9` 依靠服务端租约自然失效,并通过两个真实客户端测量消失时间。
44
+ - 公屏接口校验在线会话、内容长度、表情白名单、速率窗口和请求幂等;公开读取只返回有限时间窗和有限条数。
45
+ - 轮询是兼容基线;接入 WebSocket/SignalR 时仍保留共享租约为事实源,并用 V8 授权接口签发短期频道权限。
46
+
47
+ ## WebGL 与 Windows 双端交付
48
+
49
+ - WebGL 与 Windows 必须来自同一个 Unity 工程、场景和语义版本;禁止用旧本地包搭配新网页版本。
50
+ - Windows 默认交付 x64 安装包,至少包含当前用户安装、开始菜单入口和卸载信息;没有明确需求时不申请管理员权限。
51
+ - 外壳应给出醒目的本地版下载入口,并同时显示版本、文件大小与 SHA-256;文件名包含语义版本,旧版本 URL 不覆盖。
52
+ - 安装包属于公开运行资产,不属于私有源码。同步 `directory` 前必须排除 `public/downloads` 等生成目录,再把完整安装包随 `dist` 走流式资产发布;禁止拆分 Base64 或伪装成源码规避单文件上限。
53
+ - 发布后从公网地址重新下载完整 EXE,比较字节数和 SHA-256;本地制包成功、MCP 返回文件 Id 或 HTTP HEAD 成功都不能替代完整回读。
54
+ - 本地验收至少覆盖静默安装、主程序存在、可启动和卸载入口;签名状态、SmartScreen 信誉和硬件帧率必须单独如实说明。
55
+
56
+ ## 商城资源
57
+
58
+ 游戏进度表使用应用前缀 `app_*`,不要占用平台保留的 `mci_*` 名称。技术幂等表可以不创建可见菜单;玩家运营表创建父菜单 + 子数据菜单,隐藏 UserId、RequestId、哈希等技术字段。
59
+
60
+ 接口策略示例:
61
+
62
+ ```json
63
+ {
64
+ "SchemaVersion": 1,
65
+ "ApiEngines": {
66
+ "app_game_bootstrap": { "Ownership": "Application", "UpgradePolicy": "Managed" },
67
+ "app_game_save": { "Ownership": "Application", "UpgradePolicy": "Managed" },
68
+ "app_game_after_save": { "Ownership": "Tenant", "UpgradePolicy": "CreateIfMissing" }
69
+ }
70
+ }
71
+ ```
72
+
73
+ 租户 Hook 使用新的稳定 Key;首次安装后归租户维护,同 Key 后续版本不能改回 `Managed`。
74
+
75
+ ## 官方发布顺序
76
+
77
+ 只有当前 MCP 明确绑定官方 `https://api.itdos.com`、`OsClient=iTdos` 且用户已授权写入时才执行:
78
+
79
+ 1. `microi_list_applications` 按精确 AppKey/中文名查重。
80
+ 2. 读取远端应用上下文、源码版本、运行版本、行版本/围栏与路由快照。
81
+ 3. 本地完成类型检查、测试、真实 Unity 构建和 dist 完整性校验。
82
+ 4. 先同步私有源码;生成的 Unity、安装包与构建证据目录不得混入源码清单。任何期望版本不一致都停止重基线。
83
+ 5. 发布不可变 Web 运行版本,回读入口、文件数、哈希、状态与公开 URL。
84
+ 6. 若同时交付 Windows,从稳定公网地址下载完整安装包并核对大小、SHA-256 和版本;在线入口还要加载真实 WASM/Data。
85
+ 7. 调用官方 `ai_app_publish_store` 生成并发布精确版本的应用商城包。超时属于结果不确定,必须回读包正文和 ZIP 后才能决定是否重试。
86
+ 8. 回读 `sys_microistore` 的 AppKey、版本、状态、预览图、包摘要与资源策略,断言 `AppVersion == PackageInfo.Version == PreparedAssets.PackageVersion`。
87
+ 9. 在官网 `/apps.html` 和 `/app-detail.html?app=<appKey>` 做公开页面回读。
88
+ 10. 在一个非官方测试租户安装,回读表、菜单、接口和 Hook 所有权;再验证升级不覆盖租户 Hook。
89
+ 11. 多人应用用两个独立浏览器会话互相验证昵称、位置、公屏;强制关闭一端,确认超过约定租约后另一端不再看到该角色。
90
+
91
+ 源码同步、运行发布、商城发布、官网可见、目标租户安装是五项独立事实。任一步只有受理 ID 或 `doing` 状态,都不能报告最终成功。
92
+
93
+ ## 版本与回滚
94
+
95
+ - 运行产物不可变;相同版本不可覆盖为不同哈希。
96
+ - 商城版本必须精确对应已验证运行版本与 Manifest。
97
+ - 升级遵循先扩展、后迁移、再收缩;新旧运行版本短暂并存时协议向前/向后兼容。
98
+ - 回滚恢复上一不可变运行版本;数据库变更需要显式兼容/补偿方案,不能用文件回滚伪装数据回滚。
@@ -0,0 +1,82 @@
1
+ # Microi.Unity SDK API
2
+
3
+ ## 包边界
4
+
5
+ `Microi.Unity` 是 Unity Package Manager 包,不是普通 .NET 类库。Runtime 代码兼容项目选定的 Unity LTS 和 C# 语言级别;Editor 代码使用独立 asmdef,不能被播放器编译。
6
+
7
+ ## Editor Toolbox 菜单与边界
8
+
9
+ | 菜单 | 能力 | 可恢复保证 |
10
+ |---|---|---|
11
+ | `Camera Points...` | 按前缀与完整层级路径导入导出 Transform/Camera | 导入注册 Unity Undo |
12
+ | `Mesh Combine...` | 对选中场景根节点按材质合并 Mesh | 精确保存源 Renderer;Restore 或 Undo;生成 Mesh 资产保留 |
13
+ | `Texture Optimization...` | 对 Project 窗口选中目录分析和修改 importer | 修改前写 `ProjectSettings/MicroiUnityBackups` JSON,可恢复 |
14
+ | `Analyze Active Scene` | Mesh、顶点、三角面、材质、Camera、Light 统计 | 只读,不把结构统计换算成虚假 FPS |
15
+ | `Analyze Camera Depth Precision` | near/far 深度比诊断 | 只读 |
16
+ | `WebGL Quality and Depth...` | Balanced/High Definition 画质和选中 Camera 深度 | 画质先备份 JSON;Camera 使用 Undo |
17
+ | `Remove Camera Components...` | 清理选中层级里的 `CameraPoint_` Camera | 仅选中范围,支持 Undo |
18
+
19
+ 禁止把工具改回全场景、全工程无范围扫描。凡是修改 AssetImporter、质量设置或生成 Mesh 的新功能,都必须先定义备份、恢复和失败中断语义。
20
+
21
+ ```text
22
+ Runtime/Api/MicroiApiClient.cs
23
+ Runtime/Api/MicroiApiModels.cs
24
+ Runtime/WebGL/MicroiWebGLBridge.cs
25
+ Runtime/WebGL/Plugins/WebGL/MicroiWebGLBridge.jslib
26
+ Editor/MicroiWebGLBuildUtility.cs
27
+ Samples~/V8ApiQuickStart/
28
+ ```
29
+
30
+ ## MicroiApiClient
31
+
32
+ 场景保持一个名称稳定的 `MicroiApiClient` GameObject。主要方法:
33
+
34
+ - `Configure(baseUrl, osClient, did)`:规范化 API 地址和租户上下文。
35
+ - `SetAuthorization(tokenOrBearerValue)`:去掉 Bearer 前缀,仅保存在内存。
36
+ - `ClearAuthorization()`:登出或宿主切换时清空会话。
37
+ - `ApplyMicroiHostContext(json)`:供 WebGL `SendMessage` 调用。
38
+ - `Post<TRequest,TData>()`:类型化 DosResult 请求。
39
+ - `PostJson()`:发送原始 JSON;ApiEngineKey 只允许字母、数字、点、下划线与短横线。
40
+
41
+ 事件:
42
+
43
+ - `HostContextApplied`:宿主上下文完成更新。
44
+ - `AuthorizationRotated`:响应头返回新 DiyToken。
45
+
46
+ 不要把 Token 暴露为可序列化字段或 Unity Inspector 字段。日志只允许记录状态,不输出请求头、Token 或完整敏感响应。
47
+
48
+ ## DosResult 模型
49
+
50
+ 成功判断同时考虑 HTTP 状态和 `Code=1`。`Code=1001/1002` 应交给宿主认证层处理,不能由 Unity 自行伪造新 Token。
51
+
52
+ ```csharp
53
+ StartCoroutine(client.Post<SaveRequest, SaveData>(
54
+ "app_unity_taoyuan_save",
55
+ request,
56
+ result => Apply(result.Data),
57
+ failure => ShowRetry(failure.Msg)));
58
+ ```
59
+
60
+ `JsonUtility` 不适合任意字典和顶层数组;复杂协议应增加稳定 DTO,或在明确兼容的 JSON 库上建立独立适配层。
61
+
62
+ ## WebGL Bridge
63
+
64
+ C# 调用:
65
+
66
+ - `MicroiWebGLBridge.NotifyReady()`
67
+ - `MicroiWebGLBridge.NotifyAuthorizationRotated(token, requestToken)`
68
+ - `MicroiWebGLBridge.Emit(eventName, jsonPayload)`
69
+
70
+ `.jslib` 只转换字符串并调用页面全局函数,不缓存会话。非 WebGL/Editor 下的业务事件可以写脱敏调试日志,便于 Play 验收。
71
+
72
+ ## Editor 构建工具
73
+
74
+ 公共构建工具负责:
75
+
76
+ - 确认 WebGL BuildTargetSupport 已安装;
77
+ - 选择场景与模板;
78
+ - 固定 WebGL 2/WASM 和兼容压缩策略;
79
+ - 建立输出目录并生成可追溯构建结果;
80
+ - 失败时返回非零进程码,不生成“成功”哨兵。
81
+
82
+ 特定游戏的场景创建、PlayerSettings 和输出路径配置放项目 Editor 脚本,调用公共工具,不硬编码进 UPM。
@@ -0,0 +1,66 @@
1
+ # 既有 Unity 工具箱提取
2
+
3
+ ## 先建立清单
4
+
5
+ 按目录和程序集记录:
6
+
7
+ - Runtime 通用脚本;
8
+ - Editor 菜单、导入器和构建工具;
9
+ - WebGL `.jslib`、模板和 JavaScript;
10
+ - 相机、路径、触发区、设备协议与客户业务脚本;
11
+ - Prefab、模型、动作、材质、贴图、字体、音频;
12
+ - 第三方 Package 与其许可证。
13
+
14
+ 同时记录 Unity 版本、渲染管线、API Compatibility Level、Scripting Backend、目标平台和程序集依赖图。
15
+
16
+ ## 分类规则
17
+
18
+ | 类型 | 去向 |
19
+ |---|---|
20
+ | 与业务无关的 API 客户端、宿主桥、构建基础能力 | `Microi.Unity/Runtime` 或 `Editor` |
21
+ | 可展示的最小使用方式 | `Microi.Unity/Samples~` |
22
+ | 场景、客户模型、设备字段、项目配置 | 原项目或独立业务项目 |
23
+ | 来源不明或限制再分发的素材 | 不进入公共包;替换或取得授权 |
24
+ | 只为旧项目兼容的适配代码 | 原项目 Adapter,不污染公共 API |
25
+
26
+ ## 安全迁移顺序
27
+
28
+ 1. 只读盘点并记录基线;不先移动文件。
29
+ 2. 复制候选公共代码到 UPM,移除业务命名和硬编码配置。
30
+ 3. 建 asmdef,限制 Runtime/Editor 引用方向。
31
+ 4. 在独立 Sample 编译并运行最小场景。
32
+ 5. 让旧项目通过 `Packages/manifest.json` 引用新 UPM。
33
+ 6. 替换旧项目调用并执行 Editor、目标平台和 WebGL 回归。
34
+ 7. 比较导出接口、序列化字段、Prefab GUID 和运行行为。
35
+ 8. 只有用户明确要求且回归通过,才考虑删除旧副本;否则保留来源并标注镜像关系。
36
+
37
+ ## 兼容性注意
38
+
39
+ - 移动脚本可能改变 `.meta` GUID,导致 Prefab/Scene 引用丢失;公共提取优先新 API + Adapter,不直接搬走序列化脚本。
40
+ - Editor-only 命名空间必须放 Editor asmdef 或 `#if UNITY_EDITOR`。
41
+ - WebGL 不支持所有线程、Socket、反射和文件系统用法;公共 API 要明确平台条件。
42
+ - Unity 内置 JSON 对字典、多态和顶层数组有限制,不能在提取时默默改变协议。
43
+ - 不把客户服务器地址、OsClient、Token、设备密钥或私有证书写入 Sample。
44
+
45
+ ## 提取验收
46
+
47
+ - UPM `package.json` 可解析,Runtime/Editor asmdef 引用无环。
48
+ - Sample 编译与 Play 通过。
49
+ - 原项目改用 UPM 后功能等价。
50
+ - WebGL 插件实际链接,无 `EntryPointNotFound`。
51
+ - 公共包扫描不含客户品牌、秘密、本机路径与未授权二进制素材。
52
+ - README 说明支持版本、安装、最小示例、平台限制和升级策略。
53
+
54
+ ## 当前官方包已提取能力
55
+
56
+ `Microi.Unity` 已从既有数字孪生项目重构以下公共能力:
57
+
58
+ - WebGL 宿主事件桥、V8/DiyToken 客户端和构建入口;
59
+ - 相机点按层级路径导入导出,导入支持 Undo;
60
+ - 选中根节点范围内的 Mesh 合并,使用精确 Renderer 引用恢复;
61
+ - 选中资源目录范围内的贴图优化,执行前保存完整 importer JSON;
62
+ - 场景结构统计、Camera 深度精度诊断和选中 Camera 的 Undo 调整;
63
+ - Balanced / High Definition WebGL 质量预设和 JSON 恢复;
64
+ - 选中层级内多余 `CameraPoint_` Camera 组件的安全清理。
65
+
66
+ 旧项目的镜头路径、位置触发区、设备字段和业务 GameManager 仍属于项目 Adapter,不进入公共包。不要把这类保留项误报为“遗漏”;只有出现两个以上无业务字段的复用项目时,再抽取新的 Runtime 模块。
@@ -0,0 +1,57 @@
1
+ # WebGL 宿主、性能与部署
2
+
3
+ ## Poster-first 生命周期
4
+
5
+ 1. 首屏只加载 DOM、主视觉和轻量构建状态。
6
+ 2. 用户点击“进入 3D”后才创建 iframe/Canvas 并下载 Loader、Data、WASM。
7
+ 3. 加载中显示真实进度,不用无限假动画。
8
+ 4. 页面不可见或离开视口时 `SendMessage(..., SetHostPaused, true)`。
9
+ 5. 重回前台恢复;离开页面调用 `Quit()` 并移除全部监听与全局回调。
10
+
11
+ 错误状态至少区分:构建缺失、Loader 下载失败、Unity 初始化失败、浏览器能力不足、网络/CORS 失败。错误页仍应保留重试、返回与文档入口。
12
+
13
+ ## 上下文注入
14
+
15
+ 宿主在 Unity ready 后调用:
16
+
17
+ ```js
18
+ unityInstance.SendMessage('MicroiApiClient', 'ApplyMicroiHostContext', JSON.stringify({
19
+ ApiBaseUrl: runtime.apiBase,
20
+ OsClient: runtime.osClient,
21
+ Authorization: runtime.token,
22
+ Did: runtime.did
23
+ }))
24
+ ```
25
+
26
+ - 不使用 `?token=`、`?osClient=` 或 `?apiBase=` 传会话。
27
+ - iframe 同源时可读取父窗口内存上下文;跨域时由父页面显式 SendMessage,不能放宽为 `postMessage('*')` 接收秘密。
28
+ - 若使用 `postMessage`,发送与接收双方都校验精确 Origin、消息类型和结构。
29
+
30
+ ## Token 轮换
31
+
32
+ Unity 发送 `(newToken, requestToken)`。宿主只在当前 Token 仍等于 `requestToken`(或统一认证库明确允许)时覆盖,防止先发请求后到达的旧响应回滚新会话。
33
+
34
+ 更新顺序:统一认证库 → 微应用宿主 → 当前内存上下文 → 再注入 Unity。任何日志和业务事件都不得携带 Token。
35
+
36
+ ## 性能分档
37
+
38
+ - 桌面 DPR 上限通常不超过 2;移动实验档建议 1.0–1.25。
39
+ - 阴影距离、级联、粒子、后处理、LOD 与贴图分辨率按设备档位联动。
40
+ - 首次下载和解压峰值要纳入浏览器内存;不能只看压缩包大小。
41
+ - 大型孪生数据按区域/层级流式加载,避免把全部模型放入一个 Data 包。
42
+ - 尊重 `prefers-reduced-motion`;DOM 外壳禁用非必要动效,Unity 内按项目需求提供镜头/粒子降级。
43
+
44
+ ## 静态服务器
45
+
46
+ 常见文件类型:
47
+
48
+ | 文件 | MIME |
49
+ |---|---|
50
+ | `.wasm` | `application/wasm` |
51
+ | `.js` | `application/javascript` |
52
+ | `.data` | `application/octet-stream` |
53
+ | `.json` | `application/json` |
54
+
55
+ 预压缩 `.gz/.br` 必须返回匹配的 `Content-Encoding`,不能只靠扩展名。若托管方不能配置响应头,构建时启用 Unity 解压回退,并实测性能。
56
+
57
+ 正式验收使用 HTTP(S),检查状态码、MIME、Content-Encoding、CORS、缓存、Service Worker、控制台错误、全屏和退出后的内存/GPU 回落。