暗影地牢——手柄适配开发方案
文档目的
本文档用于明确《暗影地牢》未来几天的手柄适配主线开发内容,统一设计方向、模块边界、输入规则与开发顺序,避免后续实现过程中出现逻辑冲突、职责混乱、输入抢占不清等问题。
总体目标
为游戏建立一套完整、稳定、可扩展的手柄适配体系,使玩家在手柄模式下可以自然完成以下核心行为:
- 容器类 UI 操作
- 世界交互操作
- 技能施法与目标选择
- 常规菜单 / actbar / 天赋树导航操作
整个适配方案遵循以下总原则:
- 键鼠模式与手柄模式并存,自动切换
- 不强行让所有场景都使用虚拟光标
- 只有“确实需要鼠标语义”的系统才启用虚拟光标
- 能用纯导航解决的 UI,一律不用虚拟光标
- 世界交互与施法逻辑必须建立手柄独立分支,而不是单纯模拟鼠标
- 后续所有新功能都必须兼容这套输入分层思路
一、整体分层设计
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
}
并由一个统一的 GamepadModeManager 或 GamepadContextManager 决定当前模式。
2. A / B / 摇杆的职责必须稳定
A 键
优先级建议:
- 当前处于虚拟光标模式时,A = 虚拟左键
- 当前处于纯 UI 导航模式时,A = Submit
- 当前处于世界交互模式时,A = 执行当前交互目标
- 当前处于施法模式时,A 不一定单独处理,通常技能键本身触发施法
B 键
优先级建议:
- 虚拟光标模式下 = 虚拟右键
- UI 导航模式下 = Cancel / 返回
- 世界模式下可作为取消目标锁定、关闭面板、取消施法预览等扩展用途
左摇杆
职责建议:
- 虚拟光标模式:控制光标移动
- 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. 目标选择逻辑
第一步:扫描候选目标
以玩家为中心,在一定半径内扫描所有可交互对象。
可配置参数建议:
scanRadiusmaxCandidatescandidateLayerMaskrequireLineOfSightmaxVerticalOffset
第二步:建立候选列表
对候选对象记录:
- 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:
职责:
- 记录当前显示详情的敌人
- 接收“技能命中敌人”的事件
- 满足冷却条件时切换当前显示对象
- 自动刷新敌人详情面板
关键参数
hoverSwitchCooldownhoverAutoHideDelaylastHoverSwitchTime
切换规则
- 命中同一敌人:刷新持续时间
- 命中新敌人:若超过切换冷却,则切换显示
- 无新命中:可延迟隐藏
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. 当前方案结论
这部分原则上延续你当前已有的方案即可,不要过度改造。
因为你已经有:
GamepadSelectablePanelGamepadUINavigationManagerGamepadUIActionManager
这说明这块的主框架已经存在,后续重点是补全特殊 UI、修修导航断链、补 firstSelected / returnSelected 即可,不属于最重的难点。
4. 本板块验收目标
- actbar 技能与道具可无光标操作
- 天赋树可无光标操作
- 设置面板逻辑稳定
- 焦点恢复正常
- Submit / Cancel 语义稳定
七、推荐新增系统结构
1. 推荐的总控模块
建议后续增加:
GamepadContextManager
统一判断当前手柄上下文:
- 是否正在使用手柄
- 是否打开容器 UI
- 是否打开普通导航 UI
- 是否在世界中可交互
- 是否在施法瞄准
对外提供:
- 当前控制模式
- 是否允许虚拟光标
- 是否允许 UI 导航
- 是否允许世界交互选择
- 是否允许施法瞄准
2. 推荐模块清单
UI相关
VirtualCursorManagerVirtualCursorInputBridgeContainerGamepadContext
世界交互相关
GamepadInteractTargetManagerGamepadInteractExecutor
施法相关
GamepadCastAimManagerGamepadEnemyHoverManager
总控相关
GamepadContextManager
八、推荐开发顺序
第一阶段:先把基础模式边界做出来
目标:
- 统一“现在手柄处于哪种模式”
- 先解决输入冲突问题
任务:
- 设计
GamepadControlMode - 设计
GamepadContextManager - 明确虚拟光标 / UI导航 / 世界交互 / 施法的互斥规则
第二阶段:先做虚拟光标模式
原因:
- 容器 UI 是最强鼠标依赖系统
- 这个板块最容易先建立可见成果
- 也能最早验证“手柄模拟鼠标”是否可行
任务:
- 虚拟光标显示与移动
- A / B 点击桥接
- Hover / Click / Drag 打通
- Shift+左键语义映射
第三阶段:做世界交互目标选择
任务:
- 扫描附近交互对象
- 默认目标选择
- 右摇杆方向切换
- 高亮与 A 交互
第四阶段:做施法瞄准系统
任务:
- 右摇杆方向获取
- 圆形施法点生成
- 技能系统读取新的 AimContext
- 命中敌人显示详情信息
第五阶段:收尾与联调
任务:
- 清理输入冲突
- 调整摇杆阈值
- 调整切换冷却
- 调整吸附 / 方向体验
- 修 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 俯视角单机游戏的路线。
后续开发中,我们会严格围绕这四大板块推进,不再零散补丁式修改。
评论