Utrzymywanie fokusu poza obiektem interfejsu użytkownika

Strona zaktualizowana :
Data utworzenia strony :

Środowisko weryfikacyjne

Windows
  • Okna 11
Edytor aparatu Unity
  • 2020.3.25f1

Wymagania wstępne dotyczące tej porady

Poniższe ustawienia zostały wcześniej wprowadzone jako warunek objaśnienia tych wskazówek.

Co było pomocne w tej wskazówce?

Oryginalna historia była gdzieś, ale nie mogłem jej znaleźć, szukając słów kluczowych.

Informacje o trybie skupienia

Obiekty interfejsu użytkownika aparatu Unity, podobnie jak każda inna aplikacja, mogą mieć fokus wskazujący, że są aktywne jako obiekty docelowe danych wejściowych. Jeśli jednak klikniesz lub dotkniesz czegokolwiek innego niż obiekt, obiekt z fokusem zniknie. Akceptowanie operacji za pomocą klawiatury lub gamepada może nie być możliwe.

W tej sekcji opisano, jak używać skryptów do sterowania fokusem, aby nie utracił fokusu w pseudo. Pamiętaj, że ta obsługa nie jest funkcją aparatu Unity i może spowodować chwilową utratę koncentracji.

Rozmieszczenie obiektów

Typ obiektu nie ma znaczenia w sterowaniu ostrością, więc umieść go odpowiednio.

Jest kolorowy, dzięki czemu łatwo zauważyć, że jest ostry.

Na razie, jeśli uruchomisz go w tym stanie, zobaczysz, że jeśli klikniesz puste miejsce po tym, jak obiekt otrzyma fokus, straci ostrość.

Kontrola, aby nie stracić koncentracji

Aby to zrobić, utwórz skrypt. Nazwa skryptu może być dowolna, ale FocusRequired pozostaw ją jako .

Wprowadź kod w następujący sposób:

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);
    }
  }
}

Nie będę wchodził w szczegóły, ale To, co robię, to zachowywanie bieżącego obiektu zaznaczenia, a jeśli "zaznaczony obiekt zniknął" lub "Zaznaczyłem obiekt, którego nie chcę zaznaczać", przywracam poprzednie zaznaczenie.

Ten komponent może być dołączony do dowolnego istniejącego obiektu, więc EventSystem dołącz go do .

Ponieważ możliwe jest określenie obiektu, który nie ma być wybierany jako właściwość, spróbujmy umieścić przycisk, którego nie chcemy wybierać.

Not Selectables jest ustawiony na .

Spróbuj go uruchomić, aby zobaczyć, jak to działa. Najpierw kliknij obiekt, aby go zaznaczyć, a następnie kliknij pusty obszar, aby nie stracił ostrości.

Można również upewnić się, że kliknięcie przycisku, który nie jest zaznaczony, nie spowoduje przesunięcia fokusu.