You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity如何实现光标与方向导航(WASD/手柄)的无缝切换?

Unity鼠标与方向导航选中状态冲突的解决方案

Unity中,通过方向导航(WASD、方向键、手柄Dpad)选中的Selectable(如按钮),与鼠标悬停触发的选中状态是相互独立的。这会引发一个常见问题:当鼠标悬停在某个按钮上时按下方向键,屏幕上会同时出现两个“选中”状态的按钮——一个是鼠标触发的高亮,另一个是方向导航触发的选中,但提交操作只会响应方向导航选中的那个按钮。这种视觉混淆极易误导用户,而且鼠标触发的高亮按钮不会设置事件系统的currentSelectedGameObject,无法直接清除残留的高亮状态。

我没有找到现成的可行解决方案,因此分享自己的实现方法,帮助遇到同类问题的开发者:

期望的无缝切换行为

用户可在鼠标、键盘、手柄控制模式间自由切换,实现光标与方向导航(WASD/Dpad)的无缝衔接:

  • 从光标切换到方向导航时,若当前无选中项,则选中屏幕预设的首个按钮*;
  • 若已有选中项,从当前选中项继续导航(例如选中第3个按钮时按上方向键,会选中第2个按钮);
  • 从方向导航切换到光标时,清除所有选中状态(因为此时鼠标大概率未悬停在任何元素上)。
    *注:我有自定义脚本可设置每个屏幕的“首个选中按钮”。

解决方案

核心思路:为每个Selectable绑定鼠标事件,在PointerEnter时触发OnSelect事件,PointerExit时触发OnDeselect事件;切换到方向输入模式时,限制鼠标移动区域,绕过Unity无法通过代码直接修改系统鼠标位置的限制。

我使用Rewired插件实现输入模式切换,切换到方向输入时触发事件,将鼠标的“移动区域”宽高设为0:
Rewired设置鼠标移动区域
鼠标移动区域限制演示

仅限制鼠标移动区域无法清除鼠标悬停的高亮(因为这种操作相当于“瞬移”光标,不会触发按钮的PointerExit事件),因此需要给所有Selectable元素挂载以下核心逻辑脚本(注:我结合了项目中的UI管理器,你可能需要根据自身需求调整):

public class ForceSelectedState: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
    public UnityEngine.UI.Button button;
 
    public void OnPointerEnter(PointerEventData eventData) {
        button.OnSelect(eventData);
    }
 
    public void OnPointerExit(PointerEventData eventData) {
        button.OnDeselect(eventData);
    }
}

请确保该脚本挂载在所有需要处理的Selectable元素上。

效果对比

  • 默认行为:默认行为演示
  • 优化后行为:优化后行为演示

如果不使用Rewired,你可以寻找其他方式限制鼠标移动区域(系统鼠标位置为只读属性,无法通过代码直接修改)。

内容的提问来源于stack exchange,提问作者The Embraced One

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:20:30