全文提要
暗影地牢——手柄适配开发方案 文档目的 本文档用于明确《暗影地牢》未来几天的手柄适配主线开发内容,统一设计方向、模块边界、输入规则与开发顺序,避免后续实现过程中出现逻辑冲突、职责混乱、输入抢占不清等问题。 总体目标 为游戏建立一套完整、稳定、可扩展的手柄适配体系,使玩家在手柄模式下可以自然完成以下核

暗影地牢——手柄适配开发方案

文档目的

本文档用于明确《暗影地牢》未来几天的手柄适配主线开发内容,统一设计方向、模块边界、输入规则与开发顺序,避免后续实现过程中出现逻辑冲突、职责混乱、输入抢占不清等问题。

总体目标

为游戏建立一套完整、稳定、可扩展的手柄适配体系,使玩家在手柄模式下可以自然完成以下核心行为:

  • 容器类 UI 操作
  • 世界交互操作
  • 技能施法与目标选择
  • 常规菜单 / actbar / 天赋树导航操作

整个适配方案遵循以下总原则:

  1. 键鼠模式与手柄模式并存,自动切换
  2. 不强行让所有场景都使用虚拟光标
  3. 只有“确实需要鼠标语义”的系统才启用虚拟光标
  4. 能用纯导航解决的 UI,一律不用虚拟光标
  5. 世界交互与施法逻辑必须建立手柄独立分支,而不是单纯模拟鼠标
  6. 后续所有新功能都必须兼容这套输入分层思路

一、整体分层设计

1. 输入模式分层

手柄适配后,游戏内输入应分为四种主要工作模式:

1)普通键鼠模式

  • 使用真实鼠标位置
  • 使用真实鼠标点击
  • 交互、施法、容器等全部维持原逻辑

2)手柄纯导航模式

适用于:

  • 设置面板
  • actbar 技能选择
  • 天赋树
  • 普通菜单
  • 各种按钮、Toggle、Slider、ScrollView 组成的界面

特点:

  • 无虚拟光标
  • 依赖 Unity Selectable Navigation
  • 左摇杆 / 十字键切换焦点
  • A 确认
  • B 返回
  • 右摇杆滚动 ScrollView 或调节 Slider

3)手柄虚拟光标模式

适用于:

  • 背包
  • 仓库
  • 商店
  • 装备栏
  • 合成栏
  • 一切本质上依赖“鼠标指针 + 点击 + 拖拽 + 右键”的容器类 UI

特点:

  • 显示虚拟光标
  • 左摇杆控制虚拟光标移动
  • A = 左键
  • B = 右键
  • 左摇杆按下 + A = Shift + 左键的快速转移逻辑
  • 本质是“手柄模拟鼠标语义”

4)手柄世界操作模式

适用于:

  • 场景交互
  • 拾取掉落物
  • 进入传送门
  • 技能施法
  • 选择可交互目标
  • 选择施法目标方向

特点:

  • 不使用虚拟光标
  • 使用“附近候选目标 + 方向选择”机制
  • 使用“摇杆方向施法”机制
  • A 作为主交互 / 确认执行键

二、核心设计原则

1. 模式切换必须清晰

任一时刻,手柄只应处于以下状态之一:

  • 纯 UI 导航
  • 虚拟光标 UI
  • 世界交互
  • 世界施法

禁止出现以下问题:

  • 虚拟光标开着,同时 Unity 导航还在乱抢焦点
  • 世界交互目标选择和施法目标选择共用一套状态导致混乱
  • 容器 UI 打开时,世界交互还在响应 A 键
  • 技能施法和拾取交互都在读取右摇杆

所以后续建议增加一个统一状态枚举,例如:

public enum GamepadControlMode
{
    None,
    UINavigation,
    VirtualCursor,
    WorldInteract,
    WorldCast
}

并由一个统一的 GamepadModeManagerGamepadContextManager 决定当前模式。

2. A / B / 摇杆的职责必须稳定

A 键

优先级建议:

  1. 当前处于虚拟光标模式时,A = 虚拟左键
  2. 当前处于纯 UI 导航模式时,A = Submit
  3. 当前处于世界交互模式时,A = 执行当前交互目标
  4. 当前处于施法模式时,A 不一定单独处理,通常技能键本身触发施法

B 键

优先级建议:

  1. 虚拟光标模式下 = 虚拟右键
  2. UI 导航模式下 = Cancel / 返回
  3. 世界模式下可作为取消目标锁定、关闭面板、取消施法预览等扩展用途

左摇杆

职责建议:

  • 虚拟光标模式:控制光标移动
  • UI 导航模式:切换 Selectable
  • 世界模式:角色移动

右摇杆

职责建议:

  • UI 导航模式:滚动 / 调节 Slider
  • 世界交互模式:切换附近交互目标
  • 世界施法模式:确定施法方向 / 目标点

也就是说,右摇杆在不同上下文中承担不同职责,但同一时刻只能有一种解释方式。


三、第一板块:虚拟光标模式(容器类 UI)

1. 适用范围

仅当“容器类 UI”打开时启用虚拟光标,包括但不限于:

  • 背包
  • 仓库
  • 商店
  • 装备栏
  • 分解 / 合成 / 强化等格子界面
  • 任意依赖鼠标悬停、拖拽、左右键的物品系统 UI

非容器 UI 不启用虚拟光标。

2. 核心目标

让玩家在手柄模式下,能够像鼠标一样操作格子物品系统,包括:

  • 指向某个格子
  • 左键拾取 / 放下物品
  • 右键使用 / 穿戴 / 快速操作
  • 拖拽物品
  • 快速转移物品
  • 触发悬停提示
  • 触发容器间移动逻辑

3. 输入映射规则

基础映射

  • 左摇杆:移动虚拟光标
  • A:左键点击
  • B:右键点击
  • 左摇杆按下 + A:Shift + 左键
  • 可选扩展:RB / LB 切页,RT / LT 容器切换

快速转移规则

PC 现有逻辑:

  • Shift + 左键 = 快速将物品移动到另一容器

手柄映射:

  • 左摇杆按下 + A = 快速转移

这类映射非常合理,因为:

  • 左摇杆按下是手柄上常见的“辅助修饰键”
  • 不会与普通 A 点击冲突
  • 容易记忆

4. 虚拟光标行为要求

光标启用条件

  • 至少有一个容器类 UI 正在打开
  • 当前输入设备为手柄
  • 当前不是纯导航 UI 狀态

光标关闭条件

  • 所有容器类 UI 关闭
  • 切回键鼠输入
  • 被更高优先级模式覆盖

光标移动要求

  • 支持死区
  • 支持速度调节
  • 支持屏幕边界限制
  • 支持不同分辨率缩放一致性
  • 最好支持“低速微调 + 高速移动”两段式体验

5. 悬停与点击机制

虚拟光标本质上必须走和鼠标同样的 UI 命中检测逻辑。

需要支持:

  • PointerEnter
  • PointerExit
  • PointerDown
  • PointerUp
  • PointerClick
  • BeginDrag
  • Drag
  • EndDrag

也就是说,最终不要只做“看起来像鼠标”,而是要真正把虚拟光标接进 UI EventSystem 射线流程里。

6. 推荐拆分模块

建议拆分为:

VirtualCursorManager

职责:

  • 虚拟光标显示 / 隐藏
  • 屏幕位置维护
  • 左摇杆移动
  • 屏幕边界限制
  • 当前 hover 对象检测

VirtualCursorInputBridge

职责:

  • A / B 转换成左键 / 右键事件
  • 左摇杆按下 + A 转成 Shift + 左键语义
  • 将输入桥接到现有 UI 事件

ContainerGamepadContext

职责:

  • 检测当前是否有容器类 UI 打开
  • 决定是否启用虚拟光标模式
  • 屏蔽普通 UI 导航输入

7. 关键难点

难点一:虚拟光标与 Unity 导航互斥

容器 UI 开启后,不能同时保留普通 Selectable 焦点乱跳。

难点二:拖拽物品

很多物品系统不是简单点击,而是:

  • 鼠标按下拾取
  • 鼠标移动拖拽
  • 鼠标抬起放下

这要求虚拟光标事件链完整。

难点三:与现有 Hand / Item 逻辑兼容

如果你当前已有“鼠标拿起物品到手上”的逻辑,虚拟光标最好复用原行为,不重写一整套物品系统。

8. 本板块开发目标验收

完成后应满足:

  • 手柄打开背包可显示虚拟光标
  • 左摇杆能移动光标
  • A 可正常拾取 / 放下 / 点击物品
  • B 可执行右键逻辑
  • 左摇杆按下 + A 可快速转移
  • Tooltip / Hover / Drag 全部正常
  • 关闭容器 UI 后自动退出虚拟光标模式

四、第二板块:交互系统(世界按键交互)

1. 设计目标

将原本偏鼠标射线悬停 + 点击交互的世界交互系统,改造成手柄友好的“附近目标选择 + A 执行交互”系统。

适用对象包括:

  • 掉落物
  • 传送门
  • 可拾取资源
  • NPC
  • 宝箱
  • 机关
  • 任意可交互实体

2. 键鼠与手柄差异

PC 模式

  • 继续沿用鼠标射线检测
  • 鼠标 hover 哪个物体,就交互哪个

手柄模式

  • 不依赖鼠标位置
  • 扫描玩家周围一定范围内所有可交互实体
  • 右摇杆按方向切换选择目标
  • 当前目标显示 hover / outline / 高亮
  • 按 A 执行交互

3. 目标选择逻辑

第一步:扫描候选目标

以玩家为中心,在一定半径内扫描所有可交互对象。

可配置参数建议:

  • scanRadius
  • maxCandidates
  • candidateLayerMask
  • requireLineOfSight
  • maxVerticalOffset

第二步:建立候选列表

对候选对象记录:

  • worldPosition
  • 与玩家的方向向量
  • 距离
  • 可见性
  • 是否当前可交互

第三步:选择当前目标

若当前没有选中目标:

  • 默认选择最近的可交互对象
  • 或优先选择玩家正前方目标

第四步:方向切换

玩家拨动右摇杆时:

  • 根据当前选中目标与其他候选目标的相对位置
  • 选择“最符合该方向”的下一个目标

例如:

  • 右摇杆向上,选择当前目标上方最近且方向匹配度最高的对象
  • 向左,则选左侧对象

这部分建议不要用“单纯世界坐标上下左右”,而是用“以当前目标为原点,结合点积 + 距离评分”来选。

4. 高亮表现

当前被选中的可交互对象,需要显示“相当于鼠标 hover”的视觉反馈,例如:

  • Outline
  • 外发光
  • 名称浮层
  • 拾取提示
  • 交互提示

注意:

  • 任何时刻只应有一个主目标高亮
  • 目标切换时必须取消上一个目标高亮
  • 候选列表为空时清空高亮

5. 交互执行

当手柄模式下按 A:

  • 若当前存在选中目标,执行其交互逻辑
  • 等价于 PC 模式对该对象执行左键交互
  • 如有右键交互需求,后续可扩展给 B 或 Y

6. 推荐拆分模块

GamepadInteractTargetManager

职责:

  • 周围交互目标扫描
  • 候选目标缓存
  • 当前目标选择
  • 方向切换
  • 高亮切换

GamepadInteractExecutor

职责:

  • A 键执行当前交互目标
  • 调用现有交互接口

InteractCandidate

数据建议:

public class InteractCandidate
{
public IInteractable Interactable;
public Transform Transform;
public Vector3 WorldPosition;
public float Distance;
public Vector2 DirectionFromPlayer;
}

7. 特殊规则建议

规则一:切换冷却

右摇杆切换目标应有最小切换间隔,避免一拨到底乱跳。

规则二:失效目标自动剔除

若目标被拾取、销毁、隐藏、超出范围,必须立刻移除。

规则三:交互优先级

同范围内若目标密集,可加入权重:

  • 最近优先
  • 正前方优先
  • 当前已锁定目标适度优先
  • 重要对象(传送门 / 宝箱)可提高权重

8. 本板块开发目标验收

完成后应满足:

  • 手柄模式下可自动扫描玩家周围交互对象
  • 默认存在一个合理当前目标
  • 右摇杆可在目标间稳定切换
  • 当前目标有清晰高亮
  • A 可正常执行交互
  • 目标失效、离开范围、对象消失时逻辑稳定

五、第三板块:施法系统(右摇杆圆形施法)

1. 设计目标

将原本“朝鼠标位置施法”的技能系统,扩展出手柄模式下的方向施法逻辑。

适用于:

  • 指向性技能
  • 投射物技能
  • 指定落点技能
  • 扇形 / 线性 / 朝向类技能
  • 自动攻击朝向选择

2. 核心思路

PC 模式:

  • 依然根据鼠标世界坐标施法

手柄模式:

  • 不再依赖鼠标点
  • 以角色为中心建立一个施法圆
  • 右摇杆方向指向圆周上的一个目标点
  • 技能朝该方向 / 该目标点施放

3. 圆形施法模型

设定:

  • 玩家位置为圆心
  • 半径为 castAimRadius
  • 右摇杆输入方向为单位向量
  • 目标点 = 玩家位置 + 方向 * 半径

这样可以把“二维鼠标点选”转换成“方向型落点选择”。

优点

  • 非常适合俯视角 ARPG
  • 直观
  • 实现成本可控
  • 容易拓展目标吸附

4. 施法方向规则

当右摇杆有输入时

  • 使用右摇杆方向
  • 更新当前施法方向
  • 技能朝这个方向施放

当右摇杆无输入时

建议保留最近一次合法方向,避免方向归零导致手感差。

当角色正在移动时

可扩展规则:

  • 没有右摇杆输入时,默认朝移动方向施法
  • 但优先级低于右摇杆方向

5. 瞄准辅助建议

后续可扩展但第一版不必过重:

1)轻度吸附

若右摇杆方向附近存在敌人,可微调瞄准方向,使技能更容易命中。

2)方向记忆

保持最近一次非零方向若干时间。

3)技能类型区分

不同技能可用不同取点方式:

  • 投射物:使用方向
  • 地面技能:使用圆周目标点
  • 锁定技能:可选取方向上最近敌人

6. 敌人 hover 信息改造

你提到一个非常关键的特殊逻辑:

原本 PC 模式下:

  • 鼠标指向哪个敌人,就展示哪个敌人的 hover 信息

手柄模式下:

  • 改为技能打中哪个敌人,就显示哪个敌人的信息
  • 并增加一个最小切换冷却时间

这个设计是对的,因为手柄模式下不存在持续精确鼠标 hover。

推荐实现方式

建立一个 GamepadEnemyHoverManager

职责:

  • 记录当前显示详情的敌人
  • 接收“技能命中敌人”的事件
  • 满足冷却条件时切换当前显示对象
  • 自动刷新敌人详情面板

关键参数

  • hoverSwitchCooldown
  • hoverAutoHideDelay
  • lastHoverSwitchTime

切换规则

  • 命中同一敌人:刷新持续时间
  • 命中新敌人:若超过切换冷却,则切换显示
  • 无新命中:可延迟隐藏

7. 推荐拆分模块

GamepadCastAimManager

职责:

  • 读取右摇杆方向
  • 维护当前施法方向
  • 计算圆周目标点
  • 提供技能系统查询

GamepadEnemyHoverManager

职责:

  • 根据命中结果切换敌人信息显示
  • 管理最小切换冷却
  • 管理显示时长

技能系统改造点

技能释放时,不应再强耦合“必须有鼠标位置”,而应改为:

  • PC:取鼠标目标点
  • Gamepad:取手柄施法目标点 / 方向

建议抽象统一接口,例如:

public struct AimContext
{
public Vector3 WorldPoint;
public Vector2 Direction;
public bool HasTargetPoint;
public bool IsGamepad;
}

8. 本板块开发目标验收

完成后应满足:

  • 手柄模式下技能可正常朝右摇杆方向释放
  • 无需鼠标也能完整战斗
  • 技能落点 / 朝向稳定
  • 命中敌人后会显示对应敌人信息
  • 敌人信息切换有最小冷却,不会疯狂跳动

六、第四板块:actbar 绑定与天赋树操作

1. 设计目标

这部分采用最轻量、最稳定的方案:

完全使用原版 Unity Selectable Navigation,不启用虚拟光标。

适用范围:

  • actbar 技能栏
  • actbar 药水栏
  • 技能选择列表
  • 消耗品选择列表
  • 天赋树 UI
  • 设置面板
  • 普通确认 / 取消 / Toggle / Slider / ScrollView UI

2. 输入规则

  • 左摇杆 / 十字键:上下左右切换
  • A:确认 / 点击
  • B:返回 / 关闭
  • 右摇杆:滚动列表 / 调节 Slider
  • 不显示虚拟光标

3. 当前方案结论

这部分原则上延续你当前已有的方案即可,不要过度改造。

因为你已经有:

  • GamepadSelectablePanel
  • GamepadUINavigationManager
  • GamepadUIActionManager

这说明这块的主框架已经存在,后续重点是补全特殊 UI、修修导航断链、补 firstSelected / returnSelected 即可,不属于最重的难点。

4. 本板块验收目标

  • actbar 技能与道具可无光标操作
  • 天赋树可无光标操作
  • 设置面板逻辑稳定
  • 焦点恢复正常
  • Submit / Cancel 语义稳定

七、推荐新增系统结构

1. 推荐的总控模块

建议后续增加:

GamepadContextManager

统一判断当前手柄上下文:

  • 是否正在使用手柄
  • 是否打开容器 UI
  • 是否打开普通导航 UI
  • 是否在世界中可交互
  • 是否在施法瞄准

对外提供:

  • 当前控制模式
  • 是否允许虚拟光标
  • 是否允许 UI 导航
  • 是否允许世界交互选择
  • 是否允许施法瞄准

2. 推荐模块清单

UI相关

  • VirtualCursorManager
  • VirtualCursorInputBridge
  • ContainerGamepadContext

世界交互相关

  • GamepadInteractTargetManager
  • GamepadInteractExecutor

施法相关

  • GamepadCastAimManager
  • GamepadEnemyHoverManager

总控相关

  • GamepadContextManager

八、推荐开发顺序

第一阶段:先把基础模式边界做出来

目标:

  • 统一“现在手柄处于哪种模式”
  • 先解决输入冲突问题

任务:

  1. 设计 GamepadControlMode
  2. 设计 GamepadContextManager
  3. 明确虚拟光标 / UI导航 / 世界交互 / 施法的互斥规则

第二阶段:先做虚拟光标模式

原因:

  • 容器 UI 是最强鼠标依赖系统
  • 这个板块最容易先建立可见成果
  • 也能最早验证“手柄模拟鼠标”是否可行

任务:

  1. 虚拟光标显示与移动
  2. A / B 点击桥接
  3. Hover / Click / Drag 打通
  4. Shift+左键语义映射

第三阶段:做世界交互目标选择

任务:

  1. 扫描附近交互对象
  2. 默认目标选择
  3. 右摇杆方向切换
  4. 高亮与 A 交互

第四阶段:做施法瞄准系统

任务:

  1. 右摇杆方向获取
  2. 圆形施法点生成
  3. 技能系统读取新的 AimContext
  4. 命中敌人显示详情信息

第五阶段:收尾与联调

任务:

  1. 清理输入冲突
  2. 调整摇杆阈值
  3. 调整切换冷却
  4. 调整吸附 / 方向体验
  5. 修 UI 焦点和世界状态切换 Bug

九、潜在风险与注意事项

1. 不要直接把所有手柄输入塞进现有 InputManager

现有 InputManager 更偏“统一输入入口”,但后续手柄适配会涉及上下文分流。
如果所有逻辑继续硬塞进去,后面会越来越乱。

建议:

  • InputManager 保留总入口职责
  • 具体行为交给专门管理器

2. 虚拟光标不要污染普通 UI 导航系统

容器 UI 和菜单 UI 最好明确分开,不要混用一套交互语义。

3. 世界交互与施法都依赖右摇杆,必须做上下文互斥

例如:

  • 平时右摇杆切换交互目标
  • 技能瞄准时右摇杆改为施法方向
  • 不能同时解释

4. Hover 语义在手柄模式下要重新定义

键鼠 hover 是“鼠标指向哪里”
手柄 hover 应拆成两类:

  • 交互 hover:当前选中的可交互对象
  • 敌人信息 hover:当前命中或锁定的敌人

5. 后续所有新增系统都必须先问自己一个问题

“这个系统在手柄模式下属于哪一种控制模式?”

只有先归类,后面才不会乱。


十、阶段性里程碑

Milestone 1:容器可玩

  • 能开背包
  • 能移动虚拟光标
  • 能拾取 / 放下 / 快速转移物品

Milestone 2:世界可玩

  • 能拾取掉落物
  • 能选传送门
  • 能和周围交互对象稳定交互

Milestone 3:战斗可玩

  • 能用右摇杆稳定施法
  • 能打怪
  • 能显示敌人信息

Milestone 4:整体可玩

  • UI、交互、战斗三者不打架
  • 键鼠 / 手柄切换稳定
  • 可以长期继续打磨细节体验

十一、未来几天的实际工作内容

接下来几天,我们默认按以下主线推进:

主线 A:手柄模式总控

  • 明确模式切换
  • 建立上下文管理器
  • 做输入优先级

主线 B:虚拟光标

  • 光标显示 / 移动
  • 点击桥接
  • 容器操作适配

主线 C:世界交互

  • 周围目标扫描
  • 方向切换
  • A 键执行交互

主线 D:施法系统

  • 右摇杆方向施法
  • 敌人信息显示改造
  • 切换冷却

主线 E:现有 UI 导航收尾

  • actbar
  • 天赋树
  • 设置
  • 焦点恢复与导航修复

十二、最终结论

这次手柄适配不是“补几个按键映射”就能完成的工作,而是一次完整的输入语义扩展。

它的本质是把原本以“鼠标为中心”的 ARPG 交互模型,拆分成以下两条并行体系:

  • 键鼠体系:继续维持鼠标精确控制
  • 手柄体系:通过上下文切换,在“虚拟光标 / 纯导航 / 方向交互 / 方向施法”之间平滑切换

这是正确路线,也是最适合暗黑类 2D 俯视角单机游戏的路线。

后续开发中,我们会严格围绕这四大板块推进,不再零散补丁式修改。