30 KiB
移动端 UI 与现有 PC UI 共存实施方案
1. 目标与结论
本方案用于把横屏移动端 UI 草图落地到现有 Godot 客户端,同时保留当前 PC UI、40250 交互语义、网络协议和玩法逻辑。
草图入口:../.planning/sketches/001-mobile-hud/index.html
总体结论:
- 不重写网络、角色、物品、技能、任务、组队和商店数据逻辑。
- PC 与移动端共用同一套客户端状态和业务控制器,分别使用不同的 HUD 与窗口布局。
- 首页 HUD、虚拟摇杆、技能盘、菜单路由和移动端输入仲裁需要新增。
- 高频窗口需要移动端专用布局;低频窗口可先套移动端容器,随后逐步重排。
- 服务端或 NPC 上下文驱动的窗口不能被菜单强制打开,菜单只能展示入口条件或导航到对应场景。
- 整体属于 UI 层中等偏大改动,但不是客户端重写。预计可复用约 70% 的现有功能逻辑。
2. 已确定的移动端设计规则
2.1 设备与视觉方向
- 横屏为唯一移动端布局方向。
- 设计基准为 844×390,布局必须适配更宽的 Android 屏幕、平板和刘海/挖孔安全区。
- 风格采用现代手游半透明 HUD、暗色玻璃、暖铜金边框和低饱和背景。
- 不直接复制其他游戏素材,只参考暗黑 ARPG 的信息层级、触控半径和功能收纳方式。
2.2 首页 HUD
┌──────────────────────────────────────────────────────────────┐
│ 名称 背包 小地图 菜单 │
│ 头像 │
│ HP/MP 目标名称与血条 │
│ 队员 1 │
│ 队员 2 当前任务追踪 │
│ │
│ 游戏世界 │
│ │
│ 移动摇杆 技能 / 普攻 │
└──────────────────────────────────────────────────────────────┘
固定规则:
- 玩家名称位于左上头像上方。
- HP、MP 和职业资源条位于头像下方,宽度与头像一致。
- 点击玩家头像进入角色、装备、技能、坐骑、表情和称号页面。
- 角色功能不出现在右上菜单。
- 组队后,队员头像、名称、HP 和距离显示在玩家头像下方;未组队时不占空间。
- 队伍不出现在社交菜单,也不设置独立按钮。
- 右上角从左到右为背包、小地图、菜单;点击小地图打开大地图。
- 当前任务条直接打开任务日志,不放入菜单。
- 底部中央不设置功能栏,只在左下和右下保留必要战斗控件。
2.3 右上菜单
菜单只保留五个一级分类:
| 一级分类 | 二级内容 |
|---|---|
| 社交 | 聊天、好友、公会、情侣、观战 |
| 成长 | 精炼、龙魂、Cube 制作 |
| 活动 | 副本、钓鱼 |
| 商业 | 商店、商城、交易、私人商店、仓库、兑换 |
| 系统 | 系统设置、游戏设置、帮助、选择角色、登出、退出 |
页面层级最多两层。二级页必须提供返回上一级和关闭两个操作。
3. 当前代码基础
3.1 UI 装配
project/game_scene.gd 已负责创建并连接以下模块:
HudInventoryUISkillUICharStatusUIQuickbarQuestLogPartyUIFriendUIGuildUILoveUIShopUIExchangeUISafeboxUIMallUICubeUIRefineUIDragonSoulUI(当前功能开关关闭)MinimapAtlasUISystemMenuUI
这些模块已经连接 M2Client 信号并负责现有功能行为。移动端不应复制这一套网络和状态处理。
3.2 现有 HUD 接口可作为兼容协议
project/net_play.gd 通过以下方法更新 Hud:
set_vitals(hp, max_hp, sp, max_sp)
set_stamina(value, max_value)
set_exp(xp, next_xp)
set_level(level)
set_energy(value, max_value)
set_target(name, hp_pct)
clear_target()
移动端 HUD 实现相同的方法后,可以直接作为 net_play.setup(..., hud_node) 的 HUD 参数,无需修改网络更新流程。
3.3 PC 固定布局不能直接缩放成移动端
当前工程基准分辨率为 1920×1080,UiManager.screen 也默认使用该尺寸。hud.gd 中状态条锚定左下且 HP 宽度为 240,现有 Python UI 脚本还包含大量固定坐标。
因此不能把整个 PC CanvasLayer 等比缩小后直接作为最终移动端 UI,否则会出现:
- 字体和触控目标过小。
- 横屏短边空间不足。
- 多窗口互相覆盖。
- 标题栏拖动、右键、鼠标悬停等 PC 交互无法在触屏完成。
- 刘海、圆角和系统手势区遮挡 UI。
3.4 当前触摸能力
现有代码已经具备:
- 单指轻点地面移动或选择实体。
- 单指拖动旋转镜头。
- 双指缩放镜头。
pointing/emulate_mouse_from_touch=false,不会把触摸再次模拟成鼠标事件。
当前已具备:
- 虚拟摇杆连续移动,以及普攻、药水和 4 个技能触摸按钮。
- UI 触点按 index 捕获,摇杆/战斗触点不会被世界点地和镜头误判;窗口打开时由
UiManager阻断世界输入。 - 双指世界手势不会生成点地移动;切后台、失焦和恢复时会释放摇杆/攻击状态。
- 背包支持点按选择、再次点按使用、点另一格移动;交易、私人商店、仓库和商城支持移动端候选列表或点按操作。
代码已覆盖:
- 技能长按瞄准、拖动调整方向和松手释放;短按仍沿用现有目标/自动射程逻辑。
- 角色属性/装备、技能、聊天/私聊、系统设置和游戏设置的移动横屏页面。
- 物品长按详情与触摸拖放、技能拖入快捷栏、快捷栏槽位交换;无法拖放时仍保留点按替代路径。
后续主要是 Android/iOS 真机上的 DPI、键盘、手势区和视觉验收。
3.5 现有队伍 UI 可直接演进
PartyUI 已经:
- 监听
party_changed和生命状态更新。 - 队伍为空时自动隐藏。
- 显示成员名字、HP、队长和角色状态。
- 点击成员可选中对应角色。
- 支持角色分配、踢人、经验分配和组队治疗。
移动端只需要增加紧凑布局模式并更换挂载位置,无需重写队伍逻辑。
4. 目标架构
GameScene
├── M2Client / NetPlay / PlayerController / GameCamera
│ └── PC 与移动端共享,不复制协议和玩法状态
│
├── UiManager
│ └── 继续管理功能窗口栈、模态遮罩和关闭顺序
│
├── DesktopUiRoot
│ ├── 当前 Hud
│ ├── 当前 Quickbar
│ └── 当前 PC 窗口布局
│
└── MobileUiRoot
├── MobileHud
│ ├── PlayerCard
│ ├── PartyHost
│ ├── TargetCard
│ ├── QuestTracker
│ ├── MinimapHost
│ └── TopRightActions
├── MobileInputOverlay
│ ├── VirtualJoystick
│ ├── AttackButton
│ ├── SkillWheel
│ └── ContextAction
├── MobileMenuDrawer
├── MobileWindowHost
└── MobileUiRoot(当前同时承担路由职责)
职责边界:
MobileHud只显示状态并发出点击信号,不直接发送网络包。MobileInputOverlay把触控动作转换为现有控制器调用。MobileUiRoot把头像、背包、小地图、任务和菜单项路由到现有 UI 控制器;后续如路由继续膨胀,再拆出独立MobileUiRouter。MobileWindowHost负责安全区、全屏面板、返回键和过渡动画。- 原有 UI 控制器继续处理数据、服务器信号和业务动作。
5. UI 模式选择
新增 UiProfile,支持 AUTO、DESKTOP、MOBILE 三种模式。
自动选择建议:
enum Mode { AUTO, DESKTOP, MOBILE }
static func resolve(mode: Mode) -> Mode:
if mode != Mode.AUTO:
return mode
return Mode.MOBILE if OS.has_feature("mobile") else Mode.DESKTOP
要求:
- Android 和 iOS 默认移动 UI。
- macOS 默认 PC UI。
- 桌面开发时允许通过项目设置或启动参数强制移动 UI,便于调试。
- 自动判断只在进入游戏时执行,切换 UI 模式需要重建 UI 根节点,避免运行中残留窗口。
建议新增项目配置:
mt/ui/profile = auto | desktop | mobile
mt/ui/mobile_scale = 1.0
mt/ui/show_touch_debug = false
6. 建议文件结构
project/ui/
├── mobile/
│ ├── mobile_ui_root.gd
│ ├── mobile_hud.gd
│ ├── mobile_input_overlay.gd
│ ├── mobile_menu_drawer.gd
│ ├── mobile_ui_router.gd
│ ├── mobile_window_host.gd
│ └── components/
│ ├── player_card.gd
│ ├── party_member_strip.gd
│ ├── quest_tracker.gd
│ ├── virtual_joystick.gd
│ ├── skill_button.gd
│ └── item_touch_slot.gd
├── desktop/
│ └── 可后续把当前 HUD 迁入,首期不要求移动文件
└── ui_profile.gd
首期不要搬动所有现有文件,以减少路径变化和回归风险。
7. 现有功能与移动端入口映射
7.1 首页直达入口
| 移动端入口 | 现有目标 | 接入方式 | 改动等级 |
|---|---|---|---|
| 玩家头像 | CharStatusUI、SkillUI |
头像打开角色容器;容器内调用现有角色/技能状态 | 中 |
| 背包 | InventoryUI.toggle() |
右上按钮经路由器调用 | 低 |
| 小地图 | AtlasUI.toggle() |
小地图自身保持显示,点击打开大地图 | 低 |
| 当前任务 | QuestLog.toggle() |
任务条点击调用;不进入菜单 | 低 |
| 队员条 | PartyUI |
增加 compact 模式,挂载到玩家头像下 | 中低 |
| 普攻 | NetPlay.set_attack_key() |
按下设为 true,抬起设为 false | 中 |
| 技能 | Quickbar.activate(slot) |
技能按钮使用现有槽位和冷却逻辑 | 中 |
| 拾取/交互 | GroundItems、NetPlay |
使用现有拾取、实体选择和场景交互路径 | 中 |
7.2 右上菜单路由
| 分类 | 功能 | 当前可否直接打开 | 移动端行为 |
|---|---|---|---|
| 社交 | 聊天 | 可以 | 调用现有聊天日志入口 |
| 社交 | 好友 | 可以 | 调用 FriendUI.toggle() |
| 社交 | 公会 | 可以 | 调用 GuildUI.toggle() |
| 社交 | 情侣 | 状态驱动 | 展示情侣状态;无关系时显示空状态 |
| 社交 | 观战 | 场景状态驱动 | 展示观战说明或当前观战状态 |
| 成长 | 精炼 | 服务器询问驱动 | 显示“前往精炼 NPC”,收到 refine_ask 后打开窗口 |
| 成长 | 龙魂 | 当前禁用 | 在 ENABLE_DRAGON_SOUL 开启前隐藏或显示未开放 |
| 成长 | Cube 制作 | NPC/服务器驱动 | 导航到制作 NPC;收到 cube_opened 后打开 |
| 活动 | 副本 | 任务/场景驱动 | 展示目标与导航,不绕过服务端进入条件 |
| 活动 | 钓鱼 | 场景驱动 | 展示说明;到达钓点后由情境按钮开始 |
| 商业 | NPC 商店 | NPC 驱动 | 导航或提示靠近 NPC,不能本地强制打开 |
| 商业 | 商城 | 服务器状态驱动 | 有商城会话时显示内容,否则显示不可用状态 |
| 商业 | 玩家交易 | 玩家交互驱动 | 选择附近玩家后发起交易 |
| 商业 | 私人商店 | 玩家/摊位驱动 | 点击摊位浏览;自己的商店进入管理模式 |
| 商业 | 仓库 | NPC/服务器驱动 | 导航到仓库 NPC,服务器打开后显示 |
| 商业 | 兑换 | NPC/任务上下文驱动 | 显示导航,不伪造兑换上下文 |
| 系统 | 设置/帮助 | 可以 | 使用移动端全屏设置页或现有控制器适配页 |
| 系统 | 选择角色/登出/退出 | 可以 | 二次确认后调用现有系统操作 |
菜单只是功能入口,不改变原服务端授权条件。
8. HUD 实施细节
8.1 MobileHud 兼容接口
MobileHud 实现与当前 Hud 相同的状态更新方法,并额外提供以下信号:
signal avatar_pressed
signal inventory_pressed
signal minimap_pressed
signal menu_pressed
signal quest_pressed(quest_id: int)
signal party_member_pressed(vid: int)
signal context_action_pressed(action: String)
GameScene 根据 UI 模式创建 Hud 或 MobileHud,并把最终对象继续传给 NetPlay。
8.2 避免重复 HUD
当前 hud.gd 自己创建状态条、小地图占位、快捷栏和背包占位,同时 GameScene 还创建正式 Quickbar、InventoryUI 和 Minimap。
移动模式必须明确只有一个拥有者:
MobileHud拥有首页状态、目标、任务、顶部按钮和触控布局。Quickbar继续拥有技能槽数据、冷却和激活逻辑,但其 PC 可视节点在移动模式隐藏。InventoryUI继续拥有背包数据和动作,但其 PC 入口隐藏。Minimap继续提供地图数据/绘制能力,移动模式把可视根节点挂入MobileHud.MinimapHost或增加 compact 布局。
不能同时显示 PC HUD 和移动 HUD。
8.3 安全区与缩放
- 根布局使用 Godot anchors,不使用整页固定坐标。
- 使用
DisplayServer.get_display_safe_area()获取安全区。 - 左上玩家区和右上按钮组至少保留安全区边距。
- 基准触控目标不小于 48dp;普攻主按钮建议 80–96dp。
- HUD 缩放按短边计算,并设置最小/最大范围,避免平板按钮过大。
- 字体单独分级,不跟随 PC 窗口做纯比例缩放。
9. 移动输入方案
9.1 虚拟摇杆
在 PlayerController 中增加移动轴输入,不模拟键盘事件:
var _mobile_axis := Vector2.ZERO
func set_mobile_axis(axis: Vector2) -> void:
_mobile_axis = axis.limit_length(1.0)
移动优先级建议:
虚拟摇杆 > PC 键盘 > 点地移动 > 无移动
摇杆输入不为零时:
- 取消当前点地目标
_is_going。 - 沿用现有相机相对方向、速度、阻挡、Actor 碰撞和动画逻辑。
- 摇杆松开后
_mobile_axis清零。 - 受击、锁定、移动技能等现有移动门继续生效。
9.2 普攻与技能
- 普攻按钮按下调用
NetPlay.set_attack_key(true),抬起或触摸取消调用false。 - 技能按钮点击调用
Quickbar.activate(slot)。 - 技能长按进入瞄准态,拖动调整方向,松手调用
Quickbar.activate_aimed();短按仍调用Quickbar.activate()。 - 方向计算、技能冷却、不可使用原因和目标选择继续由现有
Quickbar/NetPlay处理。 - 触摸取消必须清理攻击按下状态,避免切后台后持续攻击。
9.3 触摸仲裁
当前 PlayerController 和 GameCamera 都接收 InputEventScreenTouch/Drag。新增移动控件后必须防止同一个触点同时操作 UI 和世界。
建议规则:
MobileInputOverlay在_gui_input中记录被 UI 捕获的 touch index。- 被捕获的 index 不传给玩家点地和镜头控制。
- 摇杆、技能、菜单、窗口区域调用
get_viewport().set_input_as_handled()。 - 未被捕获的单指仍用于点地/选中或镜头拖动。
- 双指缩放只统计世界区域中的触点。
- 模态窗口打开时阻止所有世界输入。
- 应用暂停、失焦、死亡和过场时强制释放全部触点状态。
建议把捕获状态集中到一个 TouchRouter,不要让每个按钮各自维护全局触点。
10. 功能窗口适配策略
10.1 三种适配级别
A. 直接复用控制器并更换入口
适用:背包开关、大地图、任务日志、好友、公会、系统菜单。
首期由 MobileUiRoot 调用现有 toggle/open/close 方法。
B. 同一控制器增加移动布局
适用:队伍、快捷栏、小地图、聊天、系统设置。
保留数据和信号,给 _build() 增加 layout_mode,分别构建 desktop/mobile 视图。
C. 拆分逻辑和视图
适用:背包、角色、技能、商店、交易、仓库、Cube 等固定坐标和拖放较重的窗口。
逐步拆成:
FeatureController:数据、信号、网络操作、校验
DesktopFeatureView:现有 PC 布局
MobileFeatureView:横屏全屏布局
首期允许保留现有控制器,并只在真正重做对应页面时拆分,避免一次性重构全部 UI。
10.2 PC 专属交互的移动替代
| PC 交互 | 移动端替代 |
|---|---|
| 鼠标悬停 tooltip | 短按选中、长按详情 |
| 右键使用/出售 | 选中后显示主操作按钮 |
| 标题栏拖动窗口 | 固定全屏或右侧面板 |
| 键盘 I/K/C/N/M | 首页入口或五类菜单 |
| 数字键/F1–F4 技能 | 右下技能盘 |
| 鼠标拖动物品 | 长按进入拖动,松手落位 |
| ESC 关闭 | 系统返回、面板关闭按钮、遮罩点击 |
11. GameScene 接入方案
建议把 UI 创建拆成三个阶段:
func _build_shared_feature_controllers() -> void:
# 创建背包、技能、任务、社交、商店等共享控制器
func _build_desktop_presentation() -> void:
# 创建当前 Hud、PC Quickbar、PC 窗口入口
func _build_mobile_presentation() -> void:
# 创建 MobileUiRoot、MobileHud、触控层和移动菜单
接入顺序:
- 创建
UiManager和共享功能控制器。 - 检测
UiProfile。 - 创建 Desktop 或 Mobile 表现层。
- 把当前 HUD 实例传给
NetPlay。 - 将
Quickbar、PlayerController、GameCamera、GroundItems注入MobileInputOverlay。 - 将现有功能控制器注入
MobileUiRoot的路由绑定。 - 地图切换或世界重载时,只重载世界相关 HUD 数据,不重建所有功能控制器。
12. 开发阶段
阶段 M1:双 UI 骨架(已完成,待真机验收)
目标:PC UI 完全不变,桌面可强制预览移动 UI。
- 增加
UiProfile。 - 增加
MobileUiRoot、安全区和横屏约束。 GameScene能在 Desktop/Mobile 表现层之间选择。- 移动 HUD 使用假数据完成布局,但不重复显示 PC HUD。
验收:
- macOS 默认仍显示现有 PC UI。
- 强制 mobile 时只显示移动 HUD。
- Android/iOS 自动选择移动 UI。
阶段 M2:首页状态与入口(已完成,待真机验收)
- 接入玩家名称、HP、MP、资源、经验、等级和状态效果。
- 接入目标名称与目标 HP。
- 接入背包、小地图、头像、任务条和五类菜单。
- 接入左上队伍紧凑条。
- 接入死亡、重连、副本目标等覆盖状态。
验收:所有首页入口打开正确功能,返回后恢复场景输入。
阶段 M3:移动与战斗触控(代码完成,待真机验收)
- 新增虚拟摇杆连续移动。
- 新增普攻、技能、药水和情境交互按钮。
- 处理触摸 index 捕获、取消、切后台和模态窗口。
- 接入技能冷却、不可使用原因和目标选择反馈。
验收:移动、镜头、攻击、技能可同时使用且不串触摸。
阶段 M4:高频功能页(部分完成)
- 角色/装备/技能全屏页:角色属性/装备、技能分类和技能升级已有横屏专用布局;角色表情也提供移动触控页。
- 背包和物品详情:背包点按操作、长按详情、数字键盘数量输入、跨窗口长按拖放已完成;仍需真机确认系统手势区和键盘共存体验。
- 任务日志和大地图:已有移动托管;大地图支持单指拖动并在双指时冻结单指拖动。
- 聊天与好友:聊天/私聊已有横屏输入页、触控按钮和弹窗返回处理,真机键盘体验待验收。
验收:不依赖右键、鼠标悬停和键盘即可完成完整操作。
阶段 M5:商业、制作与系统(部分完成)
- 商店、商城、交易、私人商店、仓库和兑换:移动端入口/候选列表/点按操作已覆盖;服务端上下文仍需联机验收。
- Cube、精炼、龙魂入口状态:Cube 配方/材料/制作和精炼按钮已有横屏触控布局,龙魂仍按功能开关控制。
- 系统设置、游戏设置、帮助、角色切换、登出和退出:系统设置/游戏设置/帮助已有横屏专用布局;系统菜单增加移动端专用横屏入口,好友、公会创建、公会邀请、商城/仓库密码、商店确认等确认弹窗已扩大触控尺寸并接入返回处理。
- 确保所有上下文窗口只在服务端允许时打开。
阶段 M6:真机验收与视觉统一(未完成)
- Android 和 iOS 安全区。
- 不同屏幕比例、分辨率和 DPI。
- 多指触控、后台恢复和断线重连(代码已接入,仍需真机/联机验收)。
- GPU/CPU/内存与触控延迟。
- 统一暗色玻璃、铜金边框、字号、按钮和动画。
13. 测试方案
13.1 自动化测试(已实现)
以下移动端专项测试已经加入项目,并与现有 PC/业务测试一起运行:
mobile_ui_test.gd:模式解析、横屏保护、安全区、HUD 状态、菜单分类和 UI/世界触点仲裁。mobile_window_host_test.gd:返回键、模态阻断和窗口栈。mobile_gesture_test.gd:长按/拖动触摸状态、技能瞄准、技能拖入快捷栏、快捷栏交换和物品触摸拖放。chat_mobile_ui_test.gd:横屏聊天日志、频道切换、私聊目标和数字键盘友好的输入页。gamescene_test.gd:PC/移动 UI 装配互斥和移动根节点接线。char_status_ui_test.gd、inventory_ui_test.gd:角色页、背包详情、数量输入和触摸操作。p8_test.gd:交易候选列表、仓库取出和移动端仓库存入候选列表。shop_cube_mall_test.gd:Cube 配方、材料添加/删除、制作按钮和移动端横屏布局。guild_creation_ui_test.gd、guild_war_skill_test.gd、help_ui_test.gd:公会、帮助和确认弹窗的移动布局。system_menu_ui_test.gd、system_option_ui_test.gd、private_shop_ui_test.gd:系统入口、设置和商业窗口的移动交互。
完整测试集当前共 78 个 *_test.gd,现有 PC UI、业务、网络、战斗和移动端测试均通过。推荐命令:
for test in $(rg --files project -g '*test.gd' | sort); do
/opt/homebrew/bin/godot --headless \
--rendering-method gl_compatibility \
--rendering-driver opengl3 \
--audio-driver Dummy \
--log-file "/tmp/mtgodot-${test##*/}.log" \
--path project --script "${test#project/}" || exit 1
done
13.2 桌面模拟验收
- 844×390、16:9 平板、超宽屏三档。
- 鼠标模拟触控验证所有移动入口。
- 强制 mobile profile 后走完登录、角色选择和游戏内 UI。
- 同一进程切换地图、死亡复活和断线重连。
13.3 Android/iOS 真机验收
- 刘海和系统手势区不遮挡按钮。
- 左手持续移动时,右手可选目标、普攻和连续释放技能。
- 两指缩放不会触发点地或技能。
- 拖动物品时不会移动角色或旋转镜头。
- 来电/切后台后,摇杆和普攻状态正确释放。
- 队伍成员变化、HP 和距离能实时更新。
- 商店、仓库、制作等页面不会绕过服务器上下文。
14. 完成标准
移动端 UI 可认为完成,必须同时满足:
- PC UI 默认行为和快捷键无回归。
- Android/iOS 自动进入移动 UI,桌面可强制预览。
- 首页严格符合已确认草图布局。
- 角色只从玩家头像进入。
- 队伍只在头像下方显示,不在社交菜单出现。
- 任务、小地图和背包保持首页直达。
- 右上菜单只有社交、成长、活动、商业、系统五类。
- 不使用键盘、鼠标右键或悬停,也能完成所有移动端操作。
- 所有功能继续使用现有服务器授权和网络包流程。
- 自动化测试、桌面模拟和 Android/iOS 真机测试均通过。
15. 改动规模与主要风险
15.1 改动规模
| 层级 | 改动规模 | 说明 |
|---|---|---|
| 网络协议与服务端 | 小/无 | 继续使用现有 M2Client 与 40250 流程 |
| 游戏状态与战斗逻辑 | 小 | 增加移动输入入口,不重写校验和攻击流程 |
| 首页 HUD | 大 | 新建移动端表现层 |
| 输入系统 | 中到大 | 摇杆、技能盘、多指仲裁是核心新增 |
| 高频功能页 | 中到大 | 背包、角色、技能、任务需重排 |
| 低频窗口 | 中 | 可分阶段适配 |
| PC UI | 小 | 原样保留,只增加模式分流 |
15.2 主要风险
- 触摸穿透:技能或摇杆触摸同时触发地面移动/镜头。
- 对策:集中式
TouchRouter,按 touch index 捕获。
- 对策:集中式
- 重复 HUD:旧 HUD、Quickbar、Minimap 与新 HUD 同时显示。
- 对策:明确 Desktop/Mobile 表现层互斥创建。
- 固定坐标窗口过小:PC Python UI 在移动端不可操作。
- 对策:高频页优先重排,低频页先用安全区容器过渡。
- 菜单绕过上下文:直接打开商店、仓库、精炼等造成无效状态。
- 对策:
MobileUiRoot区分“可直接打开”和“需要 NPC/服务器状态”。
- 对策:
- PC 回归:共享控制器重构影响键盘和鼠标行为。
- 对策:首期新增并行表现层,拆分控制器时补双端测试。
- 横屏安全区差异:按钮被刘海或系统边缘手势遮挡。
- 对策:运行时读取安全区并保留可配置边距。
16. 推荐首个实现切片
首个可真机验证的垂直切片已经完成,当前作为移动端联调基线:
UI 模式选择
→ 移动 HUD
→ 头像/背包/地图/任务/菜单入口
→ 左上队伍条
→ 虚拟摇杆
→ 普攻 + 4 个技能
→ Android 真机战斗验证
该切片已让客户端具备可用的移动端首页和核心战斗能力;角色、背包、技能等全屏页也已按使用频率完成移动布局,剩余工作集中在真机/联机验收和视觉微调。
17. 当前实现状态
截至 2026-09-04,代码已完成首个垂直切片,并继续补齐了部分商业/制作页面:
project/ui/ui_profile.gd:AUTO/DESKTOP/MOBILE模式选择,支持移动设备自动识别、mt/ui/profile配置和--mobile-ui/--desktop-ui预览参数。project/ui/mobile/mobile_ui_root.gd:移动端 CanvasLayer 根节点,按 844×390 横屏设计基准自适应缩放并处理功能路由。project/ui/mobile/mobile_hud.gd:名称、头像、同宽 HP/MP、目标、队伍紧凑条、任务入口、背包/小地图/菜单入口。project/ui/mobile/mobile_input_overlay.gd、virtual_joystick.gd、mobile_touch_button.gd:虚拟摇杆、普攻、药水、4 个技能触控按钮、触摸取消和失焦释放。project/ui/mobile/mobile_input_overlay.gd、project/player_controller.gd:集中记录移动 UI 触点,避免“摇杆 + 世界触点”触发点地移动。project/ui/mobile/mobile_menu_drawer.gd:社交、成长、活动、商业、系统五类两级菜单。project/player_controller.gd:新增移动轴输入,沿用现有相机相对移动、阻挡、动画和状态门。project/ui/char_status_ui.gd:角色属性/装备和表情移动横屏页面,属性点仍走原/stat命令。project/ui/skill_ui.gd、project/ui/quickbar.gd:技能移动横屏列表、升级和一键放入快捷栏空位。project/ui/inventory_ui.gd:物品长按详情、使用/选择操作和移动端数字键盘数量输入。project/ui/chat_ui.gd:横屏聊天日志、频道切换和私聊输入页。project/ui/system_option_ui.gd、project/ui/game_option_ui.gd:横屏系统/游戏设置页,保留原配置和服务器命令。project/ui/help_ui.gd、project/ui/system_menu_ui.gd:横屏帮助页和移动模式下的帮助路由。project/ui/minimap.gd:复用现有小地图绘制和数据,移动模式挂载到右上 HUD;点击地图仍打开大地图。project/ui/party_ui.gd、quickbar.gd、quest_log.gd:移动模式隐藏 PC 表现层,保留原数据和业务控制器。project/game_scene.gd:PC/移动表现层互斥装配,移动端控制器注入统一路由;PC HUD 默认路径保持不变。project/ui/safebox_ui.gd:移动端背包候选列表,点按存入、点按取出和重复请求保护。project/ui/cube_ui.gd:移动端横屏双列滚动布局,配方、材料添加/删除和制作按钮均可触摸。project/ui/refine_ui.gd:移动端横屏精炼信息与操作布局。project/ui/guild_ui.gd:移动端横屏公会四页布局、成员/技能/公会战/公告的触控按钮和创建公会弹窗。project/ui/system_menu_ui.gd:保留桌面原始系统菜单,移动端使用横屏专用系统菜单,入口和服务器命令保持一致。project/ui/friend_ui.gd、project/game_scene.gd、project/ui/shop_ui.gd、project/ui/mall_ui.gd、project/ui/safebox_ui.gd:确认弹窗移动触控尺寸与 Android 返回优先取消处理。project/ui/ui_manager.gd、project/ui/mobile/mobile_window_host.gd:动态 Button 触摸桥接、原生确认弹窗登记、模态阻断、返回顺序和安全区变化重排。project/ui/reconnect_ui.gd、project/app_flow.gd:游戏内断线保留GameScene,显示移动重连遮罩,自动重新进入上次角色。project/project.godot:增加移动 UI 配置项和横屏方向设置。
当前验证结果:
- 全部 78 个
*_test.gd通过,包括app_flow_lifecycle_test.gd、p10_test.gd、mobile_ui_test.gd、mobile_window_host_test.gd和mobile_gesture_test.gd;Godot 脚本解析检查通过。
尚未完成的部分包括:Android/iOS 真机安全区、不同屏幕比例、多指、后台恢复、性能与触控延迟验收,以及商业页面在真实服务器上下文下的联机验收。断线重连的代码路径已经完成:游戏中断线会保留当前 GameScene、显示遮罩并自动重新进入上次角色,但仍需要在真机和真实服务器上验证网络切换、后台恢复及重连失败边界。低频页面仍需要在真机上做字号、键盘和安全区的视觉微调;当前不能据此视为最终移动端交付完成。