我想对应用程序中的所有按钮使用显式导航。 但对于一些按钮,我想离开"选择右边"使用自动导航(例如:我知道左,上,下的下一个按钮,但我不知道下一个右键)。
答案 0 :(得分:3)
如果设置了值,则需要创建可以使用显式导航的自定义Selectable
。您可以将此代码用于您的案例,只需在检查器中留下需要使用自动导航的空白字段。
using UnityEngine;
using UnityEngine.UI;
namespace UI.CustomSelectable
{
public class CustomSelectable : Selectable
{
[SerializeField]
private Selectable upSelectable;
[SerializeField]
private Selectable downSelectable;
[SerializeField]
private Selectable leftSelectable;
[SerializeField]
private Selectable rightSelectable;
public override Selectable FindSelectableOnUp()
{
return upSelectable != null ? upSelectable : base.FindSelectableOnUp();
}
public override Selectable FindSelectableOnDown()
{
return downSelectable != null ? downSelectable : base.FindSelectableOnDown();
}
public override Selectable FindSelectableOnLeft()
{
return leftSelectable != null ? leftSelectable : base.FindSelectableOnLeft();
}
public override Selectable FindSelectableOnRight()
{
return rightSelectable != null ? rightSelectable : base.FindSelectableOnRight();
}
}
}
答案 1 :(得分:0)
我基于覆盖 Find...() 方法的想法编写了一个自定义按钮类。也许它对其他人有用。 它为原始答案添加了一些便利功能,例如可能的候选选项列表和检查器按钮以自动填充您的候选选项。
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace YourNameSpace
{
/// <summary>
/// Adds lists for each navigation direction.
/// The first valid selectable in each list will be used or (if none is valid)
/// then auto navigation will be used as fallback.
/// </summary>
public class ButtonSmartNavigation : Button
{
public List<Selectable> UpSelectables;
public List<Selectable> DownSelectables;
public List<Selectable> LeftSelectables;
public List<Selectable> RightSelectables;
public override Selectable FindSelectableOnUp()
{
var upSelectable = getFirstSelectable(UpSelectables, this.navigation.selectOnUp);
return upSelectable != null ? upSelectable : base.FindSelectableOnUp();
}
public override Selectable FindSelectableOnDown()
{
var downSelectable = getFirstSelectable(DownSelectables, this.navigation.selectOnDown);
return downSelectable != null ? downSelectable : base.FindSelectableOnDown();
}
public override Selectable FindSelectableOnLeft()
{
var leftSelectable = getFirstSelectable(LeftSelectables, this.navigation.selectOnLeft);
return leftSelectable != null ? leftSelectable : base.FindSelectableOnLeft();
}
public override Selectable FindSelectableOnRight()
{
var rightSelectable = getFirstSelectable(RightSelectables, this.navigation.selectOnRight);
return rightSelectable != null ? rightSelectable : base.FindSelectableOnRight();
}
protected Selectable getFirstSelectable(List<Selectable> list, Selectable defaultExplicit)
{
if (list == null)
return null;
for (int i = 0; i < list.Count; i++)
{
if (list[i] != null && list[i].IsInteractable() && list[i].gameObject.activeInHierarchy)
{
return list[i];
}
}
return defaultExplicit;
}
public void AddUpSelectable(Selectable selectable, bool prioritize = false)
{
addSelectable(UpSelectables, selectable, prioritize);
}
public void AddDownSelectable(Selectable selectable, bool prioritize = false)
{
addSelectable(DownSelectables, selectable, prioritize);
}
public void AddLeftSelectable(Selectable selectable, bool prioritize = false)
{
addSelectable(LeftSelectables, selectable, prioritize);
}
public void AddRightSelectable(Selectable selectable, bool prioritize = false)
{
addSelectable(RightSelectables, selectable, prioritize);
}
protected void addSelectable(List<Selectable> list, Selectable selectable, bool prioritize)
{
if (list == null)
{
list = new List<Selectable>();
}
if (prioritize)
{
list.Insert(0, selectable);
}
else
{
list.Add(selectable);
}
}
public void Clear()
{
UpSelectables.Clear();
DownSelectables.Clear();
LeftSelectables.Clear();
RightSelectables.Clear();
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(ButtonSmartNavigation), true)]
[CanEditMultipleObjects]
public class ButtonSmartNavigationEditor : UnityEditor.UI.ButtonEditor
{
protected SerializedProperty upSelectables;
protected SerializedProperty downSelectables;
protected SerializedProperty leftSelectables;
protected SerializedProperty rightSelectables;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var target = this.target as ButtonSmartNavigation;
if (upSelectables == null) upSelectables = serializedObject.FindProperty("UpSelectables");
if (downSelectables == null) downSelectables = serializedObject.FindProperty("DownSelectables");
if (leftSelectables == null) leftSelectables = serializedObject.FindProperty("LeftSelectables");
if (rightSelectables == null) rightSelectables = serializedObject.FindProperty("RightSelectables");
EditorGUILayout.LabelField("Smart Navigation", EditorStyles.boldLabel);
GUILayout.BeginHorizontal();
if (GUILayout.Button("Up"))
{
target.UpSelectables.Clear();
target.AddUpSelectable(target.FindSelectableOnUp());
EditorUtility.SetDirty(target);
}
if (GUILayout.Button("Down"))
{
target.DownSelectables.Clear();
target.AddDownSelectable(target.FindSelectableOnDown());
EditorUtility.SetDirty(target);
}
if (GUILayout.Button("Left"))
{
target.LeftSelectables.Clear();
target.AddLeftSelectable(target.FindSelectableOnLeft());
EditorUtility.SetDirty(target);
}
if (GUILayout.Button("Right"))
{
target.RightSelectables.Clear();
target.AddRightSelectable(target.FindSelectableOnRight());
EditorUtility.SetDirty(target);
}
if (GUILayout.Button("Clear"))
{
target.Clear();
EditorUtility.SetDirty(target);
}
GUILayout.EndHorizontal();
serializedObject.Update();
EditorGUILayout.PropertyField(upSelectables, new GUIContent("Up Selectables"));
EditorGUILayout.PropertyField(downSelectables, new GUIContent("Down Selectables"));
EditorGUILayout.PropertyField(leftSelectables, new GUIContent("Left Selectables"));
EditorGUILayout.PropertyField(rightSelectables, new GUIContent("Right Selectables"));
serializedObject.ApplyModifiedProperties();
}
}
#endif
}