UI系统组件
This commit is contained in:
54
Assets/_Game/Scripts/UI/UISelectionRestorer.cs
Normal file
54
Assets/_Game/Scripts/UI/UISelectionRestorer.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.InputSystem.UI;
|
||||
|
||||
namespace BaseGames.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// 多设备 UI 焦点守护:挂在持有 EventSystem 的对象上。
|
||||
///
|
||||
/// 解决"鼠标点击空白处 → 当前选中被清空 → 切换到键盘/手柄时无选中项可导航"的问题:
|
||||
/// 记录最近一个有效选中项;当选中丢失且玩家按下导航/确认键(键盘方向键 / 手柄摇杆·十字键 / Submit)时,
|
||||
/// 自动把焦点恢复到上一个仍可交互的选中项。仅在"导航意图"出现时恢复,不与鼠标悬停/点击冲突。
|
||||
///
|
||||
/// 设备无关:依赖 <see cref="InputSystemUIInputModule"/> 的 move/submit Action,
|
||||
/// 因此键盘、Xbox、Switch、PlayStation 手柄(均归一为 Gamepad 布局)统一生效。
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(100)]
|
||||
public class UISelectionRestorer : MonoBehaviour
|
||||
{
|
||||
private GameObject _lastSelected;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var es = EventSystem.current;
|
||||
if (es == null) return;
|
||||
|
||||
var current = es.currentSelectedGameObject;
|
||||
if (current != null && current.activeInHierarchy)
|
||||
{
|
||||
_lastSelected = current; // 记录最近的有效选中
|
||||
return;
|
||||
}
|
||||
|
||||
// 选中已丢失:仅当出现导航/确认意图时才恢复,避免抢占鼠标操作
|
||||
if (!NavigationIntentThisFrame(es)) return;
|
||||
if (_lastSelected == null || !_lastSelected.activeInHierarchy) return;
|
||||
|
||||
var sel = _lastSelected.GetComponent<Selectable>();
|
||||
if (sel == null || !sel.IsInteractable()) return;
|
||||
|
||||
es.SetSelectedGameObject(_lastSelected);
|
||||
}
|
||||
|
||||
private static bool NavigationIntentThisFrame(EventSystem es)
|
||||
{
|
||||
if (es.currentInputModule is not InputSystemUIInputModule m) return false;
|
||||
|
||||
if (m.move != null && m.move.action != null && m.move.action.WasPerformedThisFrame()) return true;
|
||||
if (m.submit != null && m.submit.action != null && m.submit.action.WasPerformedThisFrame()) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user