Запазване на фокуса извън обекта на потребителския интерфейс

Страницата се актуализира :
Дата на създаване на страница :

Среда за проверка

Уиндоус
  • Прозорци 11
Редактор на единство
  • 2020.3.25ф1

Предпоставки за този съвет

Следните настройки са направени предварително като предпоставка за обяснението на тези съвети.

Какво намерихте за полезно в този съвет?

Оригиналната история беше някъде, но не можах да я намеря чрез търсене на ключови думи.

За фокуса

Обектите на потребителския интерфейс на Unity, както и всяко друго приложение, могат да имат фокус, който показва, че те са активни като входни цели. Ако обаче щракнете или докоснете нещо различно от обекта, обектът с фокус ще изчезне. Възможно е да не е възможно да се приемат операции с клавиатура или геймпад.

Този раздел описва как да използвате скриптове, за да контролирате фокуса, така че да не губи фокус в псевдо. Имайте предвид, че тази поддръжка не е функция на 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 бутонът е настроен на .

Опитайте се да го изпълните, за да видите как работи. Първо, кликнете върху обект, за да го изберете, и след това кликнете върху празна област, така че да не губи фокус.

Можете също така да се уверите, че щракването върху бутон, който е настроен да бъде неизбран, не премества фокуса.