Files
mtgodot-poc/docs/MOBILE-UI-IMPLEMENTATION.md

30 KiB
Raw Permalink Blame History

移动端 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 已负责创建并连接以下模块:

  • Hud
  • InventoryUI
  • SkillUI
  • CharStatusUI
  • Quickbar
  • QuestLog
  • PartyUI
  • FriendUI
  • GuildUI
  • LoveUI
  • ShopUI
  • ExchangeUI
  • SafeboxUI
  • MallUI
  • CubeUI
  • RefineUI
  • DragonSoulUI(当前功能开关关闭)
  • Minimap
  • AtlasUI
  • SystemMenuUI

这些模块已经连接 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,支持 AUTODESKTOPMOBILE 三种模式。

自动选择建议:

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 首页直达入口

移动端入口 现有目标 接入方式 改动等级
玩家头像 CharStatusUISkillUI 头像打开角色容器;容器内调用现有角色/技能状态
背包 InventoryUI.toggle() 右上按钮经路由器调用
小地图 AtlasUI.toggle() 小地图自身保持显示,点击打开大地图
当前任务 QuestLog.toggle() 任务条点击调用;不进入菜单
队员条 PartyUI 增加 compact 模式,挂载到玩家头像下 中低
普攻 NetPlay.set_attack_key() 按下设为 true,抬起设为 false
技能 Quickbar.activate(slot) 技能按钮使用现有槽位和冷却逻辑
拾取/交互 GroundItemsNetPlay 使用现有拾取、实体选择和场景交互路径

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 模式创建 HudMobileHud,并把最终对象继续传给 NetPlay

8.2 避免重复 HUD

当前 hud.gd 自己创建状态条、小地图占位、快捷栏和背包占位,同时 GameScene 还创建正式 QuickbarInventoryUIMinimap

移动模式必须明确只有一个拥有者:

  • 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 触摸仲裁

当前 PlayerControllerGameCamera 都接收 InputEventScreenTouch/Drag。新增移动控件后必须防止同一个触点同时操作 UI 和世界。

建议规则:

  1. MobileInputOverlay_gui_input 中记录被 UI 捕获的 touch index。
  2. 被捕获的 index 不传给玩家点地和镜头控制。
  3. 摇杆、技能、菜单、窗口区域调用 get_viewport().set_input_as_handled()
  4. 未被捕获的单指仍用于点地/选中或镜头拖动。
  5. 双指缩放只统计世界区域中的触点。
  6. 模态窗口打开时阻止所有世界输入。
  7. 应用暂停、失焦、死亡和过场时强制释放全部触点状态。

建议把捕获状态集中到一个 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 首页入口或五类菜单
数字键/F1F4 技能 右下技能盘
鼠标拖动物品 长按进入拖动,松手落位
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、触控层和移动菜单

接入顺序:

  1. 创建 UiManager 和共享功能控制器。
  2. 检测 UiProfile
  3. 创建 Desktop 或 Mobile 表现层。
  4. 把当前 HUD 实例传给 NetPlay
  5. QuickbarPlayerControllerGameCameraGroundItems 注入 MobileInputOverlay
  6. 将现有功能控制器注入 MobileUiRoot 的路由绑定。
  7. 地图切换或世界重载时,只重载世界相关 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.gdinventory_ui_test.gd:角色页、背包详情、数量输入和触摸操作。
  • p8_test.gd:交易候选列表、仓库取出和移动端仓库存入候选列表。
  • shop_cube_mall_test.gd:Cube 配方、材料添加/删除、制作按钮和移动端横屏布局。
  • guild_creation_ui_test.gdguild_war_skill_test.gdhelp_ui_test.gd:公会、帮助和确认弹窗的移动布局。
  • system_menu_ui_test.gdsystem_option_ui_test.gdprivate_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 可认为完成,必须同时满足:

  1. PC UI 默认行为和快捷键无回归。
  2. Android/iOS 自动进入移动 UI,桌面可强制预览。
  3. 首页严格符合已确认草图布局。
  4. 角色只从玩家头像进入。
  5. 队伍只在头像下方显示,不在社交菜单出现。
  6. 任务、小地图和背包保持首页直达。
  7. 右上菜单只有社交、成长、活动、商业、系统五类。
  8. 不使用键盘、鼠标右键或悬停,也能完成所有移动端操作。
  9. 所有功能继续使用现有服务器授权和网络包流程。
  10. 自动化测试、桌面模拟和 Android/iOS 真机测试均通过。

15. 改动规模与主要风险

15.1 改动规模

层级 改动规模 说明
网络协议与服务端 小/无 继续使用现有 M2Client 与 40250 流程
游戏状态与战斗逻辑 增加移动输入入口,不重写校验和攻击流程
首页 HUD 新建移动端表现层
输入系统 中到大 摇杆、技能盘、多指仲裁是核心新增
高频功能页 中到大 背包、角色、技能、任务需重排
低频窗口 可分阶段适配
PC UI 原样保留,只增加模式分流

15.2 主要风险

  1. 触摸穿透:技能或摇杆触摸同时触发地面移动/镜头。
    • 对策:集中式 TouchRouter,按 touch index 捕获。
  2. 重复 HUD:旧 HUD、Quickbar、Minimap 与新 HUD 同时显示。
    • 对策:明确 Desktop/Mobile 表现层互斥创建。
  3. 固定坐标窗口过小PC Python UI 在移动端不可操作。
    • 对策:高频页优先重排,低频页先用安全区容器过渡。
  4. 菜单绕过上下文:直接打开商店、仓库、精炼等造成无效状态。
    • 对策:MobileUiRoot 区分“可直接打开”和“需要 NPC/服务器状态”。
  5. PC 回归:共享控制器重构影响键盘和鼠标行为。
    • 对策:首期新增并行表现层,拆分控制器时补双端测试。
  6. 横屏安全区差异:按钮被刘海或系统边缘手势遮挡。
    • 对策:运行时读取安全区并保留可配置边距。

16. 推荐首个实现切片

首个可真机验证的垂直切片已经完成,当前作为移动端联调基线:

UI 模式选择
→ 移动 HUD
→ 头像/背包/地图/任务/菜单入口
→ 左上队伍条
→ 虚拟摇杆
→ 普攻 + 4 个技能
→ Android 真机战斗验证

该切片已让客户端具备可用的移动端首页和核心战斗能力;角色、背包、技能等全屏页也已按使用频率完成移动布局,剩余工作集中在真机/联机验收和视觉微调。

17. 当前实现状态

截至 2026-09-04,代码已完成首个垂直切片,并继续补齐了部分商业/制作页面:

  • project/ui/ui_profile.gdAUTO/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.gdvirtual_joystick.gdmobile_touch_button.gd:虚拟摇杆、普攻、药水、4 个技能触控按钮、触摸取消和失焦释放。
  • project/ui/mobile/mobile_input_overlay.gdproject/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.gdproject/ui/quickbar.gd:技能移动横屏列表、升级和一键放入快捷栏空位。
  • project/ui/inventory_ui.gd:物品长按详情、使用/选择操作和移动端数字键盘数量输入。
  • project/ui/chat_ui.gd:横屏聊天日志、频道切换和私聊输入页。
  • project/ui/system_option_ui.gdproject/ui/game_option_ui.gd:横屏系统/游戏设置页,保留原配置和服务器命令。
  • project/ui/help_ui.gdproject/ui/system_menu_ui.gd:横屏帮助页和移动模式下的帮助路由。
  • project/ui/minimap.gd:复用现有小地图绘制和数据,移动模式挂载到右上 HUD;点击地图仍打开大地图。
  • project/ui/party_ui.gdquickbar.gdquest_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.gdproject/game_scene.gdproject/ui/shop_ui.gdproject/ui/mall_ui.gdproject/ui/safebox_ui.gd:确认弹窗移动触控尺寸与 Android 返回优先取消处理。
  • project/ui/ui_manager.gdproject/ui/mobile/mobile_window_host.gd:动态 Button 触摸桥接、原生确认弹窗登记、模态阻断、返回顺序和安全区变化重排。
  • project/ui/reconnect_ui.gdproject/app_flow.gd:游戏内断线保留 GameScene,显示移动重连遮罩,自动重新进入上次角色。
  • project/project.godot:增加移动 UI 配置项和横屏方向设置。

当前验证结果:

  • 全部 78 个 *_test.gd 通过,包括 app_flow_lifecycle_test.gdp10_test.gdmobile_ui_test.gdmobile_window_host_test.gdmobile_gesture_test.gdGodot 脚本解析检查通过。

尚未完成的部分包括:Android/iOS 真机安全区、不同屏幕比例、多指、后台恢复、性能与触控延迟验收,以及商业页面在真实服务器上下文下的联机验收。断线重连的代码路径已经完成:游戏中断线会保留当前 GameScene、显示遮罩并自动重新进入上次角色,但仍需要在真机和真实服务器上验证网络切换、后台恢复及重连失败边界。低频页面仍需要在真机上做字号、键盘和安全区的视觉微调;当前不能据此视为最终移动端交付完成。