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/
作者
JCxYIS
發佈於
2022-11-30
許可協議
CC BY-NC-SA 4.0