Files
youle_cocos/docs/superpowers/specs/2026-08-27-ui-asset-and-skin-design.md
T
joywayerandClaude Opus 5 cd064756d6 fix(spec): 修正 §6 回填中对"构建阻塞原因"的过度概括
发现 build-game.mjs 已实现真无头 CLI 构建(CocosCreator.exe --build),
真正卡住假设1的是"造不出 Auto Atlas 资产"而非"构建跑不完",回填措辞据此更正。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 22:33:14 +08:00

343 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# framework/ui 资源归属 · 皮肤机制 · 打包裁剪 设计
> 状态:已与用户确认(brainstorming 通过),待转 writing-plans。
> 适用工程:`cocoscreator_projects/YouleNexus`(框架真源)+ `cocoscreator_projects/games/*`(子游戏)。
> 关联:架构 spec `2026-06-28-cocos-framework-design.md` §2(monorepo + junction)/§5(换肤覆盖机制)/§7(new-game)/§8(版本升级);配置 spec `2026-06-28-config-channel-design.md`(远程参数归属)。
> **本 spec 取代架构 spec §5 的落地形式**(见 §0.3),是 `framework/ui` 层动工的前置。
> 后续另立 spec:组件替换(`SeatView` 契约、约定节点名、注册机制、按人数布局配置)。
---
## 0. 目标与背景
### 0.1 三条需求
1. **R1 独立打包**:每个子游戏独立构建发布,包内**不含任何其它子游戏**的资源与代码。
2. **R2 各自皮肤**:每个子游戏的平台界面皮肤可以不同。
3. **R3 框架可传播**:框架改动(代码、界面、资源)方便传播到所有子游戏,消灭旧架构"人工替换到每个子游戏"的痛点。
### 0.2 决策依据(旧项目实测数据)
本 spec 的关键取舍不是推测,来自对旧 H5 项目的全量比对。**记录在此,便于日后回看为什么这么定。**
**平台 UI 代码在子游戏间几乎完全相同**:`js/00_Surface/11_GameUI.js` 模板 9862 行,`doudizhu` / `niuniu` / `majiang_jx` 与模板各只差 **18 行**,且这 18 行是功能开关(手机绑定是否走验证码、地址判定条件),**不是布局差异**。
> 例外:`erqiwang` 该文件仅 4629 行、与模板差 12379 行——属另一代模板,非同源演化,不作为依据。
**平台美术资源是"同名覆盖"模式**(`Game_Surface_3/assets` vs `doudizhu/assets`,全量 446 个文件,其中 444 个为可比对 PNG):
| 项 | 数量 | 占比(基数 444) |
|---|---|---|
| 内容完全相同(共用) | 328 | 73.9% |
| 被替换(同名不同内容) | 116 | 26.1% |
| — 其中**尺寸一致** | 114 | 占被替换的 **98.3%** |
| — 其中尺寸不同 | 2 | 占被替换的 1.7% |
| 非 PNG(未比对) | 2 | 不计入基数 |
| **子游戏缺失的文件** | **0** | — |
**推论(本 spec 的三块基石):**
- 约 74% 的平台资源在子游戏间共用 → **框架必须带一套完整默认皮肤**,否则这 328 张相同的图要在每个子游戏各存一份,且框架改了不会传播(违反 R3)。
- 文件清单完全一致、0 个缺失 → **同名路径覆盖**是充分的皮肤机制。
- 98.3% 的替换是同尺寸 → **"只换图片内容、保留 `.meta`"这条约束现实可行**;剩余 1.7% 走例外通道(§3.2)。
### 0.3 本 spec 取代架构 spec §5 的什么
架构 spec §5 的**方向保留**(子游戏定制全部落在自己的 `game/` 目录、框架真源一字节不改),**落地形式改变**:
| | 架构 spec §5 原方案 | 本 spec 方案 |
|---|---|---|
| 覆盖时机 | 运行时 `AssetResolver.load(逻辑路径)` 先查 override 后回退 | **构建期合成**(§5) |
| 资源加载 | 必须动态加载 | 保持**静态引用** |
**改变理由**:Cocos 中 Prefab 上的 `SpriteFrame` 是 UUID 硬引用,运行时覆盖机制拦不到;要让 `AssetResolver` 生效就必须把资源放进 `resources/` 或 Bundle,而那一档**无法被依赖树裁剪、全量进包**——被覆盖掉的框架默认资源会成为每个包里的死重量(按数据约 26%),直接损害 R1;同时框架 UI 将无法使用"美术在编辑器里拖图"这一 Cocos 主流开发方式。
前置事实(已与用户确认):**美术产出同名替换包、不进编辑器**,因此"编辑器里所见即所得地看到子游戏皮肤"不是需求,构建期合成的唯一代价被消除。
### 0.4 已确认决策
- 皮肤合成放**构建期**,框架资源保持**散图 + Auto Atlas**(Cocos 的自动图集在构建期才真正打包)。
- 框架带**完整默认皮肤**,子游戏只覆盖需要改的部分。
- theme 契约覆盖**资源覆盖 + 视觉变量 + 布局参数**三项;**平台功能开关不进 theme**,走远程配置(复用 `config/remote-config.ts` 的 `getParam`)。
- 定制通道共**三条**,组件替换是主力通道之一(§1),其完整设计另立 spec。
### 0.5 红线
- **服务器零改动**(CLAUDE.md 第一准则):本 spec 不涉及协议,`roomtype` / `deskinfo` 等协议契约归 `GameModule`,不进 theme(§4.1)。
- **数据源权威唯一、下游不兜底**(CLAUDE.md 第二准则):可覆盖资源清单**不另建文件**,框架文件树即清单(§3.1);override 匹配不上一律**报错中止**,不静默跳过(§3.2)。theme 的缺省值是该准则的**明文例外**,理由见 §4.3。
---
## 1. 三条定制通道
子游戏定制平台界面只有三条路,边界不得混淆:
| 通道 | 管什么 | 机制 | 本 spec |
|---|---|---|---|
| **资源覆盖** | 换图、换音效、换 Spine | 同名路径替换,构建期合成 | §2 §3 §5 |
| **theme 变量** | 颜色、字体、字号、坐标/尺寸数值 | 编译期配置对象 | §4 |
| **组件替换** | 换结构、换布局、换人数 | **注册**不同的 Prefab + 可选行为覆写 | 另立 spec |
**边界规则:**
1. **资源覆盖与组件替换是两条不同的路。** override 是"换同名资源的**内容**",组件替换是"注册一个不同的**实现**"。自定义 Prefab **不走** override 的同名校验体系,不放 `override/` 目录。
2. **能用 theme 解决的不做组件替换**,能用资源覆盖解决的不改 theme。就低不就高。
3. 三条通道的产物**全部落在子游戏 `game/` 目录**,框架真源一字节不改。
> **判断修正记录**:架构 spec §5 将插槽/组件定制定位为"辅",依据是旧项目布局高度一致(0 个文件缺失)。该数据反映的是**旧架构的能力上限**(旧项目只能靠 `Game_Config.Info.position[]` 硬配坐标微调),非新框架的目标。新框架需灵活支持**不同人数的不同布局**,故组件替换升格为主力通道。
---
## 2. 资源归属规则
**唯一判定标准:凡是放进 `framework/` 的,都会出现在每一个子游戏的包里。**
### 规则 1 — 框架带完整一套默认皮肤,不是占位图
依据 §0.2:73.9% 的平台资源在子游戏间共用。框架若不带默认,这部分要在每个子游戏各存一份,框架改了不会传播(违反 R3)。附带收益:新子游戏零美术即可跑通。
### 规则 2 — `framework/ui/` 只放"所有子游戏都需要"的平台界面资源
判定问句:**下一个子游戏还需要它吗?** 否则放子游戏 `game/`。
需主动挡住的反例:两三个子游戏共用的对局资源(如麻将与跑得快共用的牌型图)。"部分子游戏共用"**不构成**进框架的理由——放进去等于让其余子游戏白背包体。这类宁可各自拷贝,也不建"部分共享层"(共享层同样会进所有包)。
### 规则 3 — 目录划分 = 图集划分,由框架单独负责
Cocos 的 Auto Atlas 只对**同目录**散图生效,因此目录结构就是性能设计。按**加载时机**切分:
```
framework/ui/
├─ atlas-common/ 全程常驻:按钮、面板底、图标、通用弹窗 (.pac)
├─ atlas-login/ 登录场景专用 (.pac)
├─ atlas-hall/ 大厅场景专用 (.pac)
├─ atlas-room/ 房间/牌桌的平台部分专用 (.pac)
├─ standalone/ 超图集尺寸上限的大图、整屏背景(不进图集)
├─ spine/ 骨骼动画
├─ audio/ 平台音效
└─ font/ 字体
```
每个场景只加载自身图集 + `atlas-common`,不会为一张图拖进整张无关大图。图集划分**是框架的事,子游戏不参与**。
该结构同时保证 `framework/ui/` 整体可在将来直接转为一个 Asset Bundle(热更预留,本期不做,见 §7)。
### 规则 4 — 子游戏侧目录与框架逻辑路径逐字对应
```
games/<name>/assets/game/
├─ override/ 与 framework/ui/ 下路径一一对应的替换资源
├─ theme.ts 视觉变量 + 布局参数
├─ prefabs/ 自定义组件 Prefab(组件替换通道,不走 override)
└─ ... 对局逻辑与对局美术(与框架无关)
```
示例:替换大厅开始按钮 → `override/atlas-hall/btn_start.png`。路径必须逐字对应,合成脚本才能机械匹配(§3)。
### 一条原有约束在本方案下解除
早期分析曾要求"框架图集里只能放不换肤的图,否则换一张要重打整个图集、影响所有子游戏"。**本方案下该约束不成立**——构建期合成发生在打图集**之前**,换肤图与不换肤图可同处一个图集,构建时用替换后的散图重打即可。图集划分因此可纯按加载时机设计,不必为换肤让路。
---
## 3. override 契约与校验
### 3.1 契约本身:框架的文件树**就是**清单
override 下每个文件的路径,必须能在 `framework/ui/` 下找到同路径的默认资源。**这是全部契约。**
**不额外维护 `skinnable-assets.json` 之类的清单文件**——那会成为第二份真相,必然与实际文件树漂移。框架资源目录本身即权威清单(第二准则:数据源权威唯一)。
### 3.2 合成脚本的校验规则(构建期阻断式)
| 情况 | 处理 |
|---|---|
| override 文件在框架里**找不到对应路径** | ❌ **报错中止构建** |
| **图片**:同名、同尺寸、仅图片文件 | ✅ 换内容,框架 `.meta` **原封不动** |
| **图片**:同名、**尺寸不同**、仅图片文件 | ❌ 报错中止,提示改为同尺寸或走例外通道 |
| **图片**:需校验尺寸却**读不出尺寸**(非 PNG,或文件损坏) | ❌ 报错中止(`size-unreadable`)——**不得**当作通过静默放行 |
| 同名、override 自带 `.meta`(**例外通道**) | ✅ 拷贝两者,把框架默认 meta 的 `uuid` 覆写进去 |
| 扩展名/格式不一致(png → jpg) | ❌ 报错中止 |
| **非图片**(音效 / 字体):同名替换 | ✅ 换内容,`.meta` 原封不动,**不做尺寸校验** |
| **Spine**(`sp.SkeletonData`):骨骼数据 + atlas + 贴图 | ✅ 须**整套一起**覆盖,缺任一件即 ❌ 报错中止 |
| 框架有、子游戏未覆盖 | ✅ 正常,用默认(**不**强制全覆盖) |
**Spine 的特殊性**:新框架使用 **Cocos 原生 Spine 支持**(`sp.Skeleton` / `sp.SkeletonData`)。
> 旧项目因 gameabc 引擎不支持 Spine 而自行集成(`SpineMgr.js` / `spine-canvas.js`),**该实现对新框架无参考价值**,资源组织方式不照搬。
在 Cocos 的资源模型里,`SkeletonData` 是一个由骨骼数据、atlas 与贴图共同构成的复合资源,三者互相引用(骨骼数据引 atlas,atlas 引贴图区域坐标)。只替换其中一件会导致运行时错位或加载失败,且这类失败**不会在构建期暴露**——故强制整套覆盖,由校验兜住。
**Spine 贴图豁免"同尺寸"约束**:普通图片要求同尺寸,是因为区域坐标记在 `.meta` 里;而 Spine 的区域坐标记在 `.atlas` 文件内,整套替换时三者自洽,故贴图尺寸可变。校验须对 Spine 贴图跳过尺寸检查,否则会误报。
**为什么必须保留 `.meta`**:UUID 存放在 `.meta` 中,删除后重新导入会生成新 UUID,导致框架 Prefab 对该资源的引用全部断裂。
**例外通道的用途**:覆盖 §0.2 中 1.7% 的尺寸变化场景(含九宫格 border、pivot 等需要随尺寸调整的元数据)。由合成脚本负责覆写 `uuid`,保证引用不断。
**错误信息要求**:报错须指出**子游戏名 + 文件相对路径 + 期望的框架路径**,做到可定位(第二准则:错误早暴露、可定位)。
合成结束打印统计:`皮肤命中 116 处,框架可覆盖资源共 446 个`——一眼看出本次合成生效的范围。
### 3.3 该校验为资源层提供了"类 tsc 保护"
框架代码改动有 `tsc` 兜底,界面与资源改动此前**没有任何保护**。本校验补上资源层:
- 框架**新增**资源 → 子游戏无需任何动作,自动用默认 ✅
- 框架**删除或重命名**资源 → 所有覆盖过它的子游戏**下次构建立刻报错**,而非悄悄退回默认皮肤
即:框架改资源路径这类会波及全部子游戏的操作,从"无人知晓是否会炸"变为"构建期即炸,且指明炸在哪个子游戏"。
### 3.4 校验可脱离构建单独运行
`npm run check-skin <name>` 只执行本节校验,不实体化、不构建,秒级反馈。程序或美术拿到替换包即可自检。构建期那次是最后一道闸,不是唯一一道。
---
## 4. theme:视觉变量与布局参数
### 4.1 边界——哪些**不**进 theme
旧项目 `Game_Config` 是大杂烩,新方案须拆干净:
| 参数 | 归属 |
|---|---|
| 颜色、字体、字号、关键坐标/尺寸 | ✅ `theme.ts` |
| `roomtype` 数组长度与结构 | ❌ **协议契约**,归 `GameModule`;须与服务器逐字节一致,见 `docs/protocol/` |
| 支持的玩家人数集合、座位数 | ❌ 子游戏固有属性,归 `GameModule` |
| 手机绑定 / 支付按钮等**功能开关** | ❌ **远程配置**,复用 `config/remote-config.ts` 的 `getParam` 分层取参 |
| 重连间隔、心跳超时等协议常量 | ❌ 框架 `core/constants.ts`,子游戏无权改 |
### 4.2 形态
纯数据对象,编译期静态,无副作用。**类型由框架定义,子游戏实现**:
```ts
// framework/ui/theme/types.ts —— 框架定义契约
export interface ThemeConfig {
colors?: { /* 主色 / 强调色 / 文字主次色 / 禁用 / 警告 */ };
fonts?: { /* 字体资源 + 各级字号 */ };
layout?: { /* 关键位置与尺寸 */ };
}
// games/<name>/assets/game/theme.ts —— 子游戏只写要改的
import type { ThemeConfig } from '.../framework/ui/theme/types';
export const theme: ThemeConfig = {
colors: { primary: '#C8102E' },
layout: { myInfoAnchorX: 130 },
};
```
相对旧项目裸 JS 的 `Game_Config`,质变在于:**字段名或类型写错,`tsc` 当场报错**,不必等到真机上发现某个值没生效。
**字段的起步集不在本 spec 穷举**——见 §4.4。
### 4.3 缺省语义:第二准则的明文例外
`ThemeConfig` 全部字段**可选**;框架处提供一份 `DEFAULT_THEME` 承载全部缺省值;合并由框架内的 `resolveTheme(gameTheme)` 完成。
这看似"兜底",但正是 CLAUDE.md 第二准则明文列出的唯一例外:*"来源本身明确定义了「可选 + 缺省语义」,且该缺省写在来源处(而非散落在各下游)"*。框架是主题的权威来源,缺省集中于 `DEFAULT_THEME` 一处,下游子游戏无需任何兜底。
> **不得以此为先例**:本例外仅适用于 theme。协议数据(如 login 响应字段)缺失仍须显式暴露,不得 `??` 抹平。
### 4.4 「可改范围」如何维护才不失控
架构 spec §10 已识别风险:"皮肤变量预留不足,子游戏被迫改框架"。解法不是预先猜全清单,而是依靠两条性质:
1. **框架 UI 组件禁止硬编码**任何颜色、字号、字体、关键坐标,一律从 `ThemeProvider` 读取。这是框架实现期的硬规矩。
2. **加字段是非破坏性的**(可选 + 有默认),任何时候都能加;**删字段或改语义才是 breaking change**,须走版本说明通知所有子游戏。
因此本 spec **只定分组与规则,不预先穷举字段**:清单是框架 UI 抽象过程的产物,逐项浮现、按需扩充。起步集 = 实现第一个平台界面时确定需要的那几个。
### 4.5 消费方式:静态读取,不做响应式
皮肤在构建期即定死,运行时不变。框架启动时 `ThemeProvider.init(resolveTheme(theme))`,其后组件纯静态读取。
**不引入响应式**——`core/reactive.ts` 的 signal 服务于会变的状态(玩家资产、房间状态);主题不变,套用只是纯粹的复杂度。运行时切换皮肤见 §7 非目标。
---
## 5. 构建流水线
一条命令,从"挂着 junction 的开发工程"产出可发布包,同时完成校验、合成、零冗余裁剪。
```
npm run build-game <name> [--platform android]
1. 版本校验 子游戏与宿主 creator.version 一致,否则中止(复用 check-cocos-version)
2. 实体化 games/<name>/ → build-workspace/<name>/
assets/framework 由 junction 变为真实目录拷贝
3. 皮肤合成 assets/game/override/** 覆盖到 assets/framework/ui/**
按 §3.2 校验;任一不合法即中止;打印命中统计
4. 构建 调 Cocos CLI 在临时工程上构建
5. 产出 拷至 dist/<name>/,写 build-info.json
```
### 5.1 四条硬规则
**① 绝不在框架真源上做合成。**
"改真源 → 构建 → 还原"的做法被否决:构建中断或崩溃会留下**被污染的真源**,而真源为所有子游戏共享的唯一副本。合成只在临时工程副本内进行,**真源全程只读**。
**② 发布链路完全不依赖 junction。**
第 2 步实体化直接从 `YouleNexus/assets/framework` 读真源拷贝,**不要求 junction 存在**。CI clone 后无需 `setup-links` 即可构建。
> junction 只服务开发期的即时性(R3);发布期靠实体化获得自包含工程。架构 spec §10 记录的风险"junction 不被 git 跟踪,团队成员环境缺链接"在发布链路上因此不复存在——不是绕过,是发布链路根本不走该路径。
**③ 临时工程不得置于 `games/` 下。**
否则 `scripts/lib/paths.mjs` 的 `listGameProjects()` 会将其识别为真实子游戏,污染 `setup-links` 与 `check-cocos-version`。固定放 `build-workspace/`,加入 `.gitignore`。
**④ Cocos 编辑器可执行文件路径只在一处定义**(环境变量或单一配置文件),其余脚本引用(第二准则常规应用)。
### 5.2 首次构建的性能问题
临时工程为全新工程,Cocos 首次打开须完整导入 assets 重建 `library`;框架 + 子游戏资源合计可达上万文件,该步骤可能耗时数分钟至十余分钟。
**对策**:保留 `build-workspace/<name>/library/` 跨次构建复用,仅在资源变化时增量导入。代价为磁盘占用(每子游戏一份 library)。
该对策列入 §6 待实测。**方案整体可行性不依赖它**(最差情况每次全量导入,只是慢),但流水线的日常可用性依赖它。
### 5.3 产物追溯:`build-info.json`
```json
{
"game": "doudizhu",
"frameworkCommit": "<git rev-parse HEAD>",
"builtAt": "<ISO 时间>",
"platform": "android",
"skin": { "matched": 116, "frameworkTotal": 446 }
}
```
落地"框架版本可追溯",成本近零:出问题可立刻查清该包所用框架版本与皮肤合成生效程度。
---
## 6. 待实测清单
以下三条是本方案的承重点,**须在第一个真实框架场景/资源出现后立即验证**,不得凭推断实现。
| # | 待验证 | 验证方法 | 失败后的备选 | 实测结论(2026-08-27,Task 2) |
|---|---|---|---|---|
| 1 | Cocos 3.8.8 的 Auto Atlas 确在**构建期**打包,构建前替换散图能被正确纳入图集 | 造一个 `.pac` 目录,替换其中一张散图后构建,检查产物图集内容 | 改为"图集整体作为覆盖单位",由子游戏提供整套 plist+png | ⏸ **阻塞(非证伪)**。真正卡住的不是"构建能否跑完",而是**"造不出一个真实的 Auto Atlas 资产"**:MCP `asset.create` 只支持 `url`/`content`/`overwrite`,没有资产类型参数;对 `.pac` 命名文件夹做 `refresh`/`reimport` 也不会把 `importer` 从 `"directory"` 转成 `"auto-atlas"`,多次独立尝试一致。(`editor.build`/`editor.open_build_panel` 确实也只打开构建面板要求人工点击——但项目自己的 `build-game.mjs` 已实现走 `CocosCreator.exe --project <dir> --build "platform=..."` 的官方无头 CLI 构建,不经过 MCP;只是本机 `COCOS_CREATOR` 未配置、也未定位到编辑器可执行文件,这条路本身也未验证可用,且即便可用也不能替代"创建 Auto Atlas"这一步——那始终是编辑器 Assets 面板 `Create > Auto Atlas` 的菜单命令,CLI 构建帮不上。)需人工在编辑器 GUI 内手动执行该菜单命令后再复测。**在此之前不得默认本假设成立去推进 Task 3 的图集相关设计。** |
| 2 | 例外通道中,除顶层 `uuid` 外,图片 `.meta` 的 `subMetas`(spriteFrame 子 uuid)是否亦需同步覆写 | 用尺寸不同的图走例外通道,检查 Prefab 引用是否仍有效 | 合成脚本一并覆写 subMetas 的 uuid | 🟡 **部分验证,范围窄于本行原意**。实测的是更基础的前提:保留原 `.meta`、只换图片内容(同尺寸)后刷新,顶层 `uuid` 与全部 `subMetas.uuid` 均未变化;换成 128×128(仍不提供新 `.meta`,未走例外通道)后刷新,顶层 `uuid` 依旧不变,且 sprite-frame 子 meta 的 `width`/`height`/`rawWidth`/`rawHeight`/`vertices`/`uv` 被 Cocos 自动重算为 128×128(前后 meta 全文见 task-2-report.md)。**未验证**的是本行字面所指的例外通道场景(override 自带一份独立生成的 `.meta`,合成脚本只覆写顶层 `uuid`,问 `subMetas` 里的子 uuid 要不要也同步覆写)——因待验证项 1 阻塞、无法在真实 `.pac` 图集环境下复测,这条更精确的问题仍待专项验证。spec §3.2 的例外通道设计**维持不变**,不降级、不简化。 |
| 3 | `build-workspace/<name>/library/` 跨次构建复用是否可靠,资源被替换后增量导入是否正确刷新 | 连续两次 build-game,第二次改动 override,比对产物 | 放弃缓存,每次全量导入(仅影响耗时) | 未测——不在 Task 2 的 Step 1-8 范围内。`build-game.mjs` 本身已在本任务执行期间落地(`134f4c8`),但"连续两次构建、比对产物"这一实测动作未做,留待专项验证。 |
| 4 | Cocos 的 `sp.SkeletonData` 在"整套替换内容、保留全部 `.meta`"后引用是否仍自洽(骨骼数据 ↔ atlas ↔ 贴图的 uuid 关联记在何处) | 用一套不同的 Spine 资源整套替换,检查场景内动画是否正常播放 | Spine 改走组件替换通道(子游戏注册自己的 `sp.Skeleton` 节点),不走资源覆盖 | ⏸ **阻塞:仓库无 Spine 素材**。`projects/*/assets/spine/` 全部为空,无任何可用 Spine 导出资源。`cocos_spine` 工具的全部 action(`info`/`list_animations`/`list_skins`/`set_animation`/`set_skin`/`set_property`/`set_data`/`add_socket`/`remove_socket`)都要求场景内已存在带 `sp.Skeleton` 组件的节点,无法凭空验证。已在 `framework/ui/README.md` 加提示,待第一套真实 Spine 资源到位后专项验证,**不假定其可行**。 |
---
## 7. 非目标(YAGNI)
- **运行时切换皮肤**(同一包内多套皮肤、节日换肤)。皮肤构建期定死;§2 的目录结构不阻碍将来扩展。
- **强制子游戏全量覆盖**。覆盖 1 个文件与覆盖 116 个文件同样合法。
- **单独的可覆盖资源清单文件**。框架文件树即清单(§3.1)。
- **`framework/ui` 的 Bundle 化热更**。§2 规则 3 的目录结构为其预留,本期不实现;是否引入需另行评估合规与版本管理成本。
- **编辑器内预览子游戏皮肤**。已确认美术不进编辑器,无此需求。
---
## 8. 与其它 spec 的接口
- **`GameModule`**(sdk spec,待写):须声明**支持的玩家人数集合**与 `roomtype` 契约。注意人数是**运行时**属性(由房间 `roomtype` 决定,同一子游戏可支持多种人数),布局须按运行时人数选取。
- **远程配置**(`config-channel-design.md`):平台功能开关与 UI 类远程参数复用 `getParam` 分层取参,本 spec 不涉及。
- **组件替换 spec**(待写):`SeatView` 契约(统一 `render(state)` 而非逐字段 setter)、约定节点名清单、注册机制、按人数的布局配置结构。其前置是 `RoomStore` 的完整建模(platform Store 第二切片)。
- **工具链**(`monorepo-scaffold-toolchain.md`):新增 `build-game` / `check-skin`;`new-game` 需增建 `override/` 与 `prefabs/` 骨架目录。