# 角色属性头像选择设计 ## 背景 `Client/Assets/Script/xmain/Module/Player` 下已有角色资料数据、资料存储和 HUD/详情面板。`PlayerProfileData` 已包含 `AvatarId`,但现有界面只显示固定的占位头像,用户无法选择头像。 当前工作区已有 54 张头像资源: `Client/Assets/Game/Art/UI/Texture/Icon/GamerPic/GamerPic_01.png` ~ `GamerPic_54.png` 本功能在现有角色资料系统上增加头像选择能力,并提供独立的选择界面。 ## 目标 - 在角色资料详情中提供“更换头像”入口。 - 展示 54 张可选头像。 - 支持点击头像后即时预览,但只有点击“确认”才保存。 - 确认后同步刷新资料详情、HUD 和其他依赖玩家资料的头像展示。 - 保持已有 `AvatarId = 0` 的旧数据兼容。 - 使用项目现有的异步资源加载、JSON UI 描述和 Prefab 生成规范。 ## 非目标 - 不新增头像解锁、付费、分类或搜索功能。 - 不修改角色战斗属性、职业或等级系统。 - 不实现服务端头像保存协议;本次只更新现有客户端 `PlayerProfileStore` 数据。 - 不重构现有 UI 资源目录或处理与本需求无关的工作区资源变更。 ## 方案 采用固定 JSON/Prefab 槽位方案,而不是运行时创建网格。 新增 `UI_PlayerAvatarPicker` Dialog 预制体,固定包含 54 个头像槽位。每个槽位直接引用一个 `GamerPic_XX` Sprite,运行时代码只处理选择、高亮、预览和确认。这样布局可在 Unity 编辑器中检查,资源引用稳定,也符合项目 UI 持久化规范。 ## 数据与资源 ### AvatarId 规则 - `0`:兼容旧存档,显示 `GamerPic_01`。 - `1`~`54`:对应同编号的 `GamerPic_XX`。 - 负数或大于 54:显示默认头像,不阻塞界面。 - 用户点击确认后保存 `1`~`54`。 ### 资源目录 - 头像:`Client/Assets/Game/Art/UI/Texture/Icon/GamerPic/` - 通用 UI 资源:使用当前工作区中已有的 `Client/Assets/Game/Art/UI/Texture/UI/Common/` 资源。 - 头像选择预制体:`Client/Assets/Game/Art/UI/Prefab/UI_PlayerAvatarPicker.prefab` - 头像选择 JSON:`Doc/UIPrefabCreater/UI_PlayerAvatarPicker.json` ## 组件边界 ### PlayerAvatarCatalog 新增头像目录类,负责: - 暴露头像数量和默认头像 ID。 - 将头像 ID 转换为 `GamerPic_XX` 资源路径。 - 将旧 ID、负数和超范围 ID 归一化为可显示的默认头像。 目录类不保存玩家状态,也不处理 UI。 ### PlayerProfileModule 扩展现有角色资料模块,负责: - 异步加载并刷新 HUD、详情面板中的头像。 - 绑定详情面板的头像入口。 - 异步打开和关闭头像选择弹窗。 - 持有临时 `pendingAvatarId`,隔离预览状态与已保存资料。 - 更新选择槽位高亮和预览头像。 - 点击确认时更新 `PlayerProfileStore`。 异步回调必须校验当前视图仍存在,且回调对应的头像 ID 仍是当前请求,避免关闭界面或快速切换时旧回调覆盖新状态。 ### PlayerProfileStore 继续作为玩家资料的唯一状态源。确认头像时通过已有 `Update` 接口修改 `AvatarId`,由 `Changed` 事件驱动所有资料视图刷新。 ## 界面设计 ### 资料详情面板 - 保留现有昵称、UID、职业、货币和战斗属性布局。 - 头像区域增加可点击的“更换头像”入口。 - 当前头像继续使用头像框包裹,并替换内部固定占位图。 ### 头像选择弹窗 挂载到 `UILayer.Dialog`,包含: - 遮罩层:点击后取消选择。 - 弹窗标题:`选择头像`。 - 当前头像预览区:头像框、预览头像和选择提示。 - 可滚动头像列表:6 列 × 9 行,共 54 个头像槽位。 - 每个头像槽位:头像 Image、选中高亮 Image、点击 Button。 - 底部按钮:`取消`、`确认`。 - 右上角关闭按钮:等同取消。 界面使用现有蓝绿描边弹窗、深色文字、TextMeshProUGUI 和通用按钮/列表资源。头像 Image 保持等比显示。 ## 交互流程 1. 用户打开角色资料详情。 2. 用户点击头像区域或更换入口。 3. 模块异步加载并实例化头像选择弹窗。 4. 弹窗以当前资料头像初始化 `pendingAvatarId` 和选中态。 5. 用户点击任意头像时,只更新预览和选中高亮。 6. 点击取消、关闭或遮罩时销毁弹窗,不调用 `PlayerProfileStore.Update`。 7. 点击确认时调用 `PlayerProfileStore.Update` 保存头像 ID,然后关闭选择弹窗。 8. `PlayerProfileStore.Changed` 触发 HUD、详情面板和头像展示刷新。 ## 异常处理 - 头像资源加载失败:保留 `ico_user` 占位头像并记录一次错误日志。 - 头像 ID 非法:按默认头像显示,不抛出 UI 阻塞异常。 - 重复点击打开:只允许一个选择弹窗实例。 - 关闭弹窗后仍返回的异步加载:丢弃回调结果。 ## 测试与验收 ### EditMode 测试 - 验证头像 ID 到 `GamerPic_XX` 路径的映射。 - 验证 0、负数和超范围 ID 都回退默认头像。 - 验证取消不会触发资料变更事件。 - 验证确认只修改 `AvatarId`,不改变其他资料字段。 - 验证头像变更后资料模块刷新 HUD 与详情视图。 - 验证 `UI_PlayerAvatarPicker.json` 通过 JSON Prefab Builder 校验。 ### Unity 编辑器验证 - 头像选择预制体可正常加载。 - 54 个头像槽位排列为 6 列 × 9 行并可滚动。 - 当前头像有选中高亮。 - 点击头像会更新预览但不会提前保存。 - 确认、取消、关闭和遮罩点击行为符合交互流程。 - 确认后的头像同时出现在资料详情和 HUD。 ## 验收标准 用户进入角色属性详情后,点击头像可以打开选择界面;选择任意头像可以即时预览但在确认前不保存;点击确认后头像 ID 保存并同步更新详情页和 HUD;取消选择后原头像保持不变。