Files
AIGame/Doc/UI_Atlas_Pipeline.md

87 lines
8.4 KiB
Markdown
Raw Permalink 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.
# UI 图集自动化方案(AIGame)
> 2026-10-22 移植 ClientTrunk 的 `SpriteAtalsGenerator`、`AssetBundleBuildRules.ProcessAtlas` 与 `GEngine.AtlasManager` 核心链路;适配本项目 Unity 2022.3、YooAsset 3.0.6、HybridCLR。
## 1. 目标
- 美术/AI 把切图放入约定目录。
- 导入为 `Sprite (2D and UI)`,关闭 mipmap。
- Prefab / 运行时按 **Sprite 短名** 引用(与 JSON `assets.sprites` 一致)。
- 图片导入、删除、移动后延迟合并更新;每个实际含图片的目录生成一个 `.spriteatlas`,构建时原图与图集同包。
## 2. 目录
```text
AIClient/Assets/Bundles/UI/Texture/
Common/ # 通用控件(对应 UI_*_Set)
<Module>/ # 业务专用
AIClient/Assets/Bundles/UI/Atlas/
UI_CommonAtlas.spriteatlas
UI_HomeAtlas.spriteatlas
UI_PrototypeAtlas.spriteatlas
```
中间产物仍可先落在 `Tools/output/`,再导入 Bundles。
## 3. 切图来源
1. 选图集级别:`UI_Simple_Set` / `UI_Normal_Set` / `UI_Pic_Set`。
2. `Tools/gpt_image_generate.py` 生成(>1K 用 `gpt-image-2-vip`,见 `ResourceCreate.md`)。
3. 风格:`Doc/Design/UI_Design_Principles.md` + `ui_design.jpg`。
4. 切片坐标以对应 `Doc/UI_*_Set.md` 为准;登记 `Doc/ResDesc_Picture.md`。
## 4. 导入建议
- Texture Type:`Sprite (2D and UI)`
- Sprite Mode:单图 `Single`;整图集再切为 `Multiple`
- Mesh Type:`Full Rect`(九宫格)
- 标准控件底图必须设置有效非零 Border,JSON 使用 `imageType: Sliced`;按钮各状态图同样设置。Common 的 26 张 Normal Set 控件由 `UiSpriteNineSliceRules.cs` 自动导入维护;新增控件时同步扩展规则。已有资源可执行 `Tools/UI/Apply Standard Control Nine-Slice` 后重建对应 Prefab。
- Alpha Is Transparency:开
- `UI/Texture/` 下原图由 `TexturePlatformPostprocessor` 保持 RGBA32、Compression=None,关闭 Crunch 和四个平台的原图覆盖;保留其他导入参数。平台压缩仅应用于最终 SpriteAtlas:Windows(Standalone)DXT5,iOS(iPhone)和 Android 为 ASTC 6×6,WebGL 为 ASTC 8×8,关闭 Crunch。目录外图片继续沿用平台压缩规则。
## 5. 自动生成与构建
`Assets/Editor/UI/UiSpriteAtlasGenerator.cs` 扫描 `Texture/` 的 Texture2D,按直接父目录分组,支持 Single / Multiple Sprite。嵌套目录独立成图集,不会被父图集重复收集。目录分隔符编码为 `_s`,下划线编码为 `_u`,防止 `A/B` 与 `A_B` 同名。根目录直接放的图片归 `UI___RootAtlas`。`UiAtlasPaths` 为编辑器和运行时提供同一套路径规则。
图集采用 SpriteAtlas V1 `AlwaysOnAtlas`;最大页尺寸 2048,padding=4,不旋转、不紧密打包、不生成 mipmap,保留 Sprite Border。图过多时由 Unity 自动产生多页。必须开启 Include in Build(与参考工程一致),使当前 SBP 的 `PackAllAtlases` 建立打包关联,`StripUnusedSpriteSources` 才能剥离未压缩原图像素。图集与原图的 Sprite 对象仍由 YooAsset 同包分发,运行时加载器保留延迟绑定兼容。
已有图集原地更新,保留 GUID。无变化不重写;仅清理带 `AIGame.UI.GeneratedAtlas` 标签且已无源图的图集,不清空 Atlas 目录。生成前检查非 Sprite 输入、目录大小写冲突和同一图集中的重复 Sprite 名。普通导入回调只调整新导入图片的 Sprite / mipmap / alpha / NPOT 设置,不修改已有九宫格边界。
`Tools/UI/Generate Sprite Atlases` 可手动校验生成。`SetupUiBundleCollector.Setup` 在 Art 构建前执行生成并配置:
| 收集内容 | 类型 | 规则 |
| --- | --- | --- |
| `UI/Prefab` | MainAssetCollector | 保留原 Prefab 名地址与独立包 |
| `UI/Atlas` | MainAssetCollector | `CollectUiAtlas` + `PackUiAtlas` |
| `UI/Texture` | DependAssetCollector | `CollectUiAtlasTexture` + `PackUiAtlas` |
图集用文件名寻址;原图不额外增加短名地址,通过依赖进入其图集同名 bundle,避免跨目录重名图片引起地址冲突。既有 Art 构建入口 `BuildAndStageArt` 已调用此 Setup,无需维护第二个构建入口。Prefab 无需重建或改用图集中的克隆 Sprite。
## 6. 运行时
`UiManager.Init` 在打开 UI 前注册 `UiAtlasLoader`。Unity 发出 `SpriteAtlasManager.atlasRequested` 后,加载器从首选包、Art、DefaultPackage 中异步加载 `UI_` 前缀图集并回调绑定。打开 Prefab 时等待在途图集加载完成。请求合并,共用图集句柄和 Sprite 克隆;失败可重试;随 UI 根节点销毁注销事件、释放句柄及克隆。
动态换图示例(Coroutine):
```csharp
yield return UiManager.Instance.Atlases.SetSpriteAsync(image, "Home", "home_ico_coin");
// 或仅加载 Sprite:
yield return UiManager.Instance.Atlases.LoadSpriteAsync("Common", "btn_primary_normal", sprite => { /* 使用 */ });
```
目录字符串替代参考项目与具体业务耦合的 `AtlasEnum`。多个并发请求不会重复加载;同一个 Image 后发请求优先。Editor 可回退 AssetDatabase 以支持本地预览,Player 全部走 YooAsset 异步加载。
## 7. 验证
`AIClient/AgentScripts/VerifyUiAtlases.cs` 通过 unity-pipeline 执行:`Editor` 校验平台参数、打包后 Sprite / Border、GUID 幂等与 Art 实际构建映射;`AutomaticChanges` 使用临时图片验证导入/移动/删除自动维护后清理;`BuildIsolated` 只向 `Tools/output/ui_atlas` 构建独立验证包,不替换 CDN / StreamingAssets;`PrepareRuntimeScene`/`Runtime`/`RestoreRuntimeScene` 在空场景实测真实资源包与禁用 Editor fallback 的异步加载,随后恢复原场景。回执同目录。
2026-10-22 验证通过:编辑器 394 项、自动增删移动 6 项、真实 WebGL 资源包的 Editor Play Mode 加载 12 项。3 个图集分别覆盖 Common 38/Home 16/Prototype 13 张图片;二次生成 updated=0,原 GUID 和九宫格边界保留。运行时验证包含 Prefab 自动绑定、并发 Sprite 缓存、Image 后发请求优先和销毁释放;没有使用 AssetDatabase fallback。`dialog.png` 为真实包内对话框的 540×960 离屏渲染,面板/按钮/关闭图标显示正常。最终恢复 Boot 场景,无未保存内容;未执行浏览器或微信真机验证。
同日原图压缩规则调整后,`ApplyUncompressedSources` 已迁移全部 67 张原图为未压缩 RGBA32,四个平台覆盖关闭,GUID 和 Border 保留;更新后的 Editor 796 项检查、自动增删移动 7 项检查均通过,最终三个图集的平台压缩规则保留。目录外图片另通过 13 项导入/重新导入检查,继续使用原平台压缩规则。原图迁移回执见 `Tools/output/ui_atlas/source_uncompressed.json`。
同日修复包体膨胀:旧的 `Include in Build=false` 导致 SBP 保留源图像素。真实 Art Home 包 `a6442d30c6c5d555575f90ae44067db5` 为 3,044,323 字节,并包含 16 个 RGBA32 Texture2D。恢复 `Include in Build=true` 后,隔离验证包为 271,138 字节,源 Texture2D 为 0,16 个 Sprite 保留;运行时真实 Home 页为 2048×1024、ASTC_8x8,实际包内 UI 渲染/动态换图/释放通过。Atlas 预览约 0.5 MiB 是纹理数据大小,bundle 经 LZ4 后可更小。`AuditUiAtlasBundle.cs` / `Tools/output/ui_atlas/size/` 提供前后对象检查与字节数,Runtime 检查已增加非空实际纹理断言。正式 Art 包须重新构建后采用本次修复。
随后完整 Art 构建还发现旧缓存问题:`20261022.142050` 的 Home 包 `ef703e962fe2343aadd151413a3e2114` 仍为 2,932,774 字节/15 个 RGBA32 原图。独立验证包不包含正式 Art 的全部 Prefab,因此此前的验证不能覆盖这些旧依赖缓存。通过 Unity 官方 `BuildCache.PurgeCache(false)` 清理 SBP 缓存后,正式 Art `20261022.142513` 的 Home 包降为 271,138 字节/0 张源 Texture2D;接着保留缓存的正式增量构建 `20261022.142810` 同样通过,均已暂存到本地 StreamingAssets 与 CDN 目录。
`UiAtlasBuildValidation.Inspect` 在正式 Art 构建完成后检查所有生成图集 bundle 的真实对象。若发现残留原图,`BuildAndStageArt` 自动清理 SBP 缓存,以 `.atlasfix` 版本后缀重建一次;仍有残留则返回失败,禁止暂存异常包。不会仅凭图集 Inspector 或构建映射判断包体正确。`AuditUiAtlasBundle.VerifyProductionGuard` 已确认能检出用户提供的坏包,并验证正式三个图集包均无源纹理;回执 `Tools/output/ui_atlas/size/production_guard.json`。