Files
AIGame/Doc/UI_Atlas_Pipeline.md

8.4 KiB
Raw Permalink Blame History

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. 目录

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):

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。