Păstrarea focalizării în afara obiectului UI

Pagina actualizată :
Data creării paginii :

Mediul de verificare

Windows
  • Ferestre 11
Unity Editor
  • 2020.3.25F1

Cerințe preliminare pentru acest sfat

Următoarele setări au fost făcute în avans ca o condiție prealabilă pentru explicarea acestor sfaturi.

Ce vi s-a părut util în acest sfat?

Povestea originală era undeva, dar nu am găsit-o căutând cuvinte cheie.

Despre Focus

Obiectele Unity UI, ca orice altă aplicație, pot avea o focalizare care indică faptul că sunt active ca ținte de intrare. Totuși, dacă faceți clic sau atingeți altceva decât obiectul, obiectul focalizat va dispărea. Este posibil să nu fie posibilă acceptarea operațiilor cu o tastatură sau un gamepad.

Această secțiune descrie modul de utilizare a scripturilor pentru a controla focalizarea, astfel încât să nu piardă focalizarea într-un pseudo. Rețineți că acest suport nu este o caracteristică Unity și vă poate face să vă pierdeți concentrarea pentru un moment.

Plasarea obiectelor

Tipul de obiect nu contează în controlul focalizării, așa că plasați-l corespunzător.

Este colorat astfel încât să fie ușor de văzut că este focalizat.

Pentru moment, dacă îl rulați în această stare, puteți vedea că dacă faceți clic pe un loc gol după ce obiectul primește focalizare, acesta își va pierde focalizarea.

Controlați astfel încât să nu vă pierdeți concentrarea

Pentru a face acest lucru, creați un script. Numele scriptului poate fi orice, dar FocusRequired lăsați-l ca .

Introduceți codul după cum urmează:

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

Nu voi intra în prea multe detalii, dar Ceea ce fac este să păstrez obiectul de selecție curent, iar dacă "obiectul selectat a dispărut" sau "Am selectat un obiect care nu doresc să fie selectat", revin la selecția anterioară.

Această componentă poate fi atașată la orice obiect care există, deci EventSystem atașați-o la .

Deoarece este posibil să specificați obiectul pe care nu doriți să fie selectat ca proprietate, să încercăm să plasăm un buton pe care nu doriți să îl selectați.

Not Selectables este setat la .

Încercați să-l rulați pentru a vedea cum funcționează. Mai întâi, faceți clic pe un obiect pentru al selecta, apoi faceți clic pe o zonă goală, astfel încât să nu piardă focalizarea.

De asemenea, vă puteți asigura că dacă faceți clic pe un buton setat să fie neselectat, focalizarea nu se deplasează.