Udržování fokusu mimo objekt uživatelského rozhraní

Stránky aktualizovány :
Datum vytvoření stránky :

Ověřovací prostředí

Windows
  • Systém Windows 11
Unity Editor
  • 2020.3.25f1

Předpoklady pro tento tip

Následující nastavení byla provedena předem jako předpoklad pro vysvětlení těchto tipů.

Co vám tento tip pomohl?

Původní příběh někde byl, ale nemohl jsem ho najít hledáním klíčových slov.

O programu Focus

Objekty uživatelského rozhraní Unity, stejně jako jakákoli jiná aplikace, můžou mít fokus, který označuje, že jsou aktivní jako vstupní cíle. Pokud však kliknete nebo se dotknete čehokoli jiného než objektu, objekt se vstupem zmizí. Může se stát, že nebude možné přijímat operace s klávesnicí nebo gamepadem.

Tato část popisuje, jak pomocí skriptování řídit fokus tak, aby neztratil fokus v pseudo. Všimněte si, že tato podpora není funkcí Unity a může způsobit, že na chvíli ztratíte fokus.

Umístění objektu

Při ovládání zaostření nezáleží na typu objektu, proto jej umístěte vhodně.

Je barevný, takže je snadno vidět, že je zaostřený.

Prozatím, pokud jej spustíte v tomto stavu, můžete vidět, že pokud kliknete na prázdné místo poté, co objekt obdrží fokus, ztratí fokus.

Ovládejte, abyste neztratili pozornost

Chcete-li to provést, vytvořte skript. Název skriptu může být libovolný, ale FocusRequired ponechte ho jako .

Zadejte kód následujícím způsobem:

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

Nebudu zabíhat do přílišných podrobností, ale To, co dělám, je, že zachovávám aktuální objekt výběru, a pokud "vybraný objekt je pryč" nebo "Vybral jsem objekt, který nechci, aby byl vybrán", vrátím se k předchozímu výběru.

Tuto komponentu lze připojit k libovolnému objektu, který existuje, proto EventSystem ji připojte k .

Vzhledem k tomu, že je možné zadat objekt, který nechcete, aby byl vybrán jako vlastnost, zkusme umístit tlačítko, které nechcete vybrat.

Not Selectables tlačítko je nastaveno na .

Zkuste jej spustit, abyste viděli, jak to funguje. Nejprve klikněte na objekt, abyste jej vybrali, a poté klikněte na prázdnou oblast, aby neztratila zaostření.

Můžete také zajistit, aby klepnutí na tlačítko, které je nastaveno jako nevybrané, nepřesunulo fokus.