將焦點放在UI物件之外

更新頁 :
頁面創建日期 :

驗證環境

窗戶
  • 窗戶 11
Unity 編輯器
  • 2020.3.25f1

此提示的先決條件

作為解釋這些提示的先決條件,已提前進行了以下設置。

你覺得這個提示有什麼説明?

原來的故事在某個地方,但我無法通過搜索關鍵字找到它。

關於Focus

與任何其他應用程式一樣,Unity UI 物件可以具有一個焦點,指示它們作為輸入目標處於活動狀態。 但是,如果按兩下或觸摸物件以外的任何物件,則具有焦點的物件將消失。 可能無法接受使用鍵盤或遊戲手柄的操作。

本節介紹如何使用腳本來控制焦點,使其不會在偽焦點中丟失焦點。 請注意,此支援不是 Unity 功能,可能會導致您暫時失去注意力。

物件放置

對象的類型在焦點控制中無關緊要,因此請適當放置。

它是彩色的,因此很容易看出它是焦點。

目前,如果在此狀態下運行它,可以看到,如果在對象獲得焦點后按下空白位置,它將失去焦點。

控制,這樣你就不會失去注意力

為此,請創建一個腳本。 文稿名稱可以是任何名稱,但 FocusRequired 將其保留為 .

按如下方式輸入代碼:

using System.Collections;
using System.Linq;                 // 追加
using UnityEngine;
using UnityEngine.EventSystems;    // 追加
using UnityEngine.UI;              // 追加

public class FocusRequired : MonoBehaviour
{
  /// <summary>
  /// <see cref="Selectable"/> をフックするクラスです。
  /// </summary>
  private class SelectionHooker : MonoBehaviour, IDeselectHandler
  {
    /// <summary>親コンポーネント。</summary>
    public FocusRequired Restrictor;

    /// <summary>
    /// 選択解除時にそれまで選択されていたオブジェクトを覚えておく。
    /// </summary>
    /// <param name="eventData"></param>
    public void OnDeselect(BaseEventData eventData)
    {
      Restrictor.PreviousSelection = eventData.selectedObject;
    }
  }

  /// <summary>選択させないオブジェクト一覧。</summary>
  [SerializeField] private GameObject[] NotSelectables;

  /// <summary>直前まで選択されていたオブジェクト。</summary>
  private GameObject PreviousSelection = null;

  /// <summary>
  /// 選択対象のオブジェクト一覧。
  /// </summary>
  private GameObject[] _selectables;

  private void Awake()
  {
    // すべての Selectable を取得する
    var selectableList = (FindObjectsOfType(typeof(Selectable)) as Selectable[]).ToList();

    // 選択除外がある場合は外す
    if (NotSelectables != null)
    {
      foreach (var item in NotSelectables)
      {
        var sel = item?.GetComponent<Selectable>();
        if (sel != null) selectableList.Remove(sel);
      }
    }

    _selectables = selectableList.Select(x => x.gameObject).ToArray();

    // フォーカス許可オブジェクトに SelectionHooker をアタッチ
    foreach (var selectable in this._selectables)
    {
      var hooker = selectable.AddComponent<SelectionHooker>();
      hooker.Restrictor = this;
    }

    // フォーカス制御用コルーチンをスタート
    StartCoroutine(RestrictSelection());
  }

  /// <summary>
  /// フォーカス制御処理。
  /// </summary>
  /// <returns></returns>
  private IEnumerator RestrictSelection()
  {
    while (true)
    {
      // 別なオブジェクトを選択するまで待機
      yield return new WaitUntil(
          () => (EventSystem.current != null) && (EventSystem.current.currentSelectedGameObject != PreviousSelection));

      // まだオブジェクトを未選択、または許可リストを選択しているなら何もしない
      if ((PreviousSelection == null) || _selectables.Contains(EventSystem.current.currentSelectedGameObject))
      {
        continue;
      }

      // 選択しているものがなくなった、または許可していない Selectable を選択した場合は前の選択に戻す
      EventSystem.current.SetSelectedGameObject(PreviousSelection);
    }
  }
}

我不會贅述太多細節,但是 我正在做的是保留當前的選擇物件,如果“所選物件已消失”或“我選擇了不想被選中的物件”,我將恢復到以前的選擇。

此元件可以附加到任何存在的物件,因此 EventSystem 請將其附加到 。

由於可以指定您不想被選為屬性的物件,因此讓我們嘗試放置一個您不想選擇的按鈕。

Not Selectables 按鈕設定為 。

嘗試運行它以查看它是如何工作的。 首先,按一個物件以將其選中,然後按下空白區域,以免它失去焦點。

您還可以確保按下設置為未選取的按鈕不會移動焦點。