510 字
3 分鐘
[Unity] 不使用滑鼠來操作 UI (UI Navigation)
在 Unity 中,如果要使用上下左右 (i.e. 鍵盤、搖桿、D-pad)控制 UI,就必須要先設定 UI Navigation。
手動啟用
先找到場景上的 Event System,設定好 First Select,也就是開啟場景時第一個被選擇的 UI 物件 (雖然這個欄位可以放所有 GameObject,但如果該 GameObject 不可以被選擇,視同沒有效果)

同時,Unity 預設的顏色都很白、不容易被察覺。這裡我們把「被選中」顏色設的明顯一點 (#39C5BB)。

使用 Navigation 設定該物件可以透過上下、左右或是我全都要來選中;
點選 Visulaization 可以看到 UI 互動的流程圖。

自動化腳本
如果懶得設定上面那些東西,我寫了個小腳本可以動態變更場景上的可選擇物件,取名叫 UiNavigationTweak 然後拉進場景裡就可以了。
using UnityEngine;using UnityEngine.UI;using System.Collections;using System.Collections.Generic;using UnityEngine.EventSystems;
public class UiNavigationTweak : MonoBehaviour{ void Start() { Refresh(); }
public void Refresh() { var selectables = Transform.FindObjectsOfType<Selectable>(); var eventSystem = GameObject.FindObjectOfType<EventSystem>(); Color32 mikuColor = new Color32(0x39, 0xc5, 0xbb, 0xff); int i = 0; // mod all selected color foreach(var selectable in selectables) { var c = selectable.colors; c.selectedColor = mikuColor; selectable.colors = c; i++; } // evs if(i > 0 && eventSystem) { eventSystem.SetSelectedGameObject(selectables[0].gameObject); Debug.Log($"[UiNavigationTweak] Modded {i} objects."); } }}:::spoiler 如果專案會動態改變 UI,可以利用定期偵測這些變更把它套用
也可以由外部腳本呼叫 Refresh()
using UnityEngine;using UnityEngine.UI;using System.Collections;using System.Collections.Generic;using UnityEngine.EventSystems;
public class UiNavigationTweak : MonoBehaviour{
/// <summary> /// Start is called on the frame when a script is enabled just before /// any of the Update methods is called the first time. /// </summary> IEnumerator Start() { while(true) { Refresh(); yield return new WaitForSeconds(1); } }
/// <summary> /// Start is called on the frame when a script is enabled just before /// any of the Update methods is called the first time. /// </summary> public void Refresh() { var selectables = Transform.FindObjectsOfType<Selectable>(); var eventSystem = GameObject.FindObjectOfType<EventSystem>(); Color32 mikuColor = new Color32(0x39, 0xc5, 0xbb, 0xff); int i = 0; // mod all selected color foreach(var selectable in selectables) { var c = selectable.colors; c.selectedColor = mikuColor; selectable.colors = c; i++; } // evs if(i > 0 && eventSystem) { Debug.Log($"[UiNavigationTweak] Modded {i} objects."); if(!eventSystem?.currentSelectedGameObject?.activeInHierarchy ?? true) eventSystem.SetSelectedGameObject(selectables[0].gameObject); } }}Unity 寫了那麼久還頭一次碰到這樣的內容…
[Unity] 不使用滑鼠來操作 UI (UI Navigation)
https://fuwari.vercel.app/posts/unity-ui-navigation/