Menjaga fokus keluar dari objek UI

Halaman Diperbarui :
Tanggal pembuatan halaman :

Lingkungan verifikasi

Windows
  • jendela 11
Editor Kesatuan
  • 25f1/3/2020

Prasyarat untuk tip ini

Pengaturan berikut telah dibuat sebelumnya sebagai prasyarat untuk penjelasan tips ini.

Apa yang menurut Anda bermanfaat dalam tip ini?

Cerita aslinya ada di suatu tempat, tetapi saya tidak dapat menemukannya dengan mencari kata kunci.

Tentang Fokus

Objek UI Unity, seperti aplikasi lainnya, dapat memiliki fokus yang menunjukkan bahwa objek tersebut aktif sebagai target input. Namun, jika Anda mengklik atau menyentuh apa pun selain objek, objek dengan fokus akan hilang. Mungkin tidak dapat menerima operasi dengan keyboard atau gamepad.

Bagian ini menjelaskan cara menggunakan skrip untuk mengontrol fokus sehingga tidak kehilangan fokus dalam pseudo. Perhatikan bahwa dukungan ini bukan fitur Unity dan dapat menyebabkan Anda kehilangan fokus sejenak.

Penempatan Objek

Jenis objek tidak masalah dalam kontrol fokus, jadi tempatkan dengan tepat.

Itu diwarnai sehingga mudah untuk melihat bahwa itu dalam fokus.

Untuk saat ini, jika Anda menjalankannya dalam keadaan ini, Anda dapat melihat bahwa jika Anda mengklik tempat kosong setelah objek menerima fokus, itu akan kehilangan fokus.

Kontrol agar Anda tidak kehilangan fokus

Untuk melakukan ini, buat skrip. Nama skrip bisa apa saja, tetapi FocusRequired biarkan sebagai .

Masukkan kode sebagai berikut:

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

Saya tidak akan membahas terlalu banyak detail, tapi Apa yang saya lakukan adalah mempertahankan objek pilihan saat ini, dan jika "objek yang dipilih hilang" atau "Saya telah memilih objek yang tidak ingin saya pilih", saya kembali ke pilihan sebelumnya.

Komponen ini dapat dilampirkan ke objek apa pun yang ada, jadi EventSystem lampirkan ke .

Karena dimungkinkan untuk menentukan objek yang tidak ingin Anda pilih sebagai properti, mari kita coba menempatkan tombol yang tidak ingin Anda pilih.

Not Selectables tombol diatur ke .

Coba jalankan untuk melihat cara kerjanya. Pertama, klik pada objek untuk memilihnya, lalu klik pada area kosong sehingga tidak kehilangan fokus.

Anda juga bisa memastikan bahwa mengklik tombol yang disetel ke batal dipilih tidak memindahkan fokus.