Mengekalkan fokus daripada objek UI

Laman dikemaskini :
Tarikh penciptaan halaman :

Persekitaran pengesahan

Windows
  • Windows 11
Penyunting Perpaduan
  • 2020.3.25f1

Prasyarat untuk petua ini

Tetapan berikut telah dibuat terlebih dahulu sebagai prasyarat untuk penjelasan petua ini.

Apa yang anda dapati membantu dalam petua ini?

Kisah asal ada di suatu tempat, tetapi saya tidak dapat menemuinya dengan mencari kata kunci.

Mengenai Fokus

Objek UI Perpaduan, seperti mana-mana apl lain, boleh mempunyai fokus yang menunjukkan bahawa ia aktif sebagai sasaran input. Walau bagaimanapun, jika anda mengklik atau menyentuh apa-apa selain objek, objek dengan fokus akan hilang. Mungkin tidak mungkin untuk menerima operasi dengan papan kekunci atau pad permainan.

Bahagian ini menerangkan cara menggunakan penskripan untuk mengawal fokus supaya ia tidak kehilangan fokus dalam pseudo. Ambil perhatian bahawa sokongan ini bukan ciri Unity dan boleh menyebabkan anda kehilangan fokus seketika.

Penempatan Objek

Jenis objek tidak penting dalam kawalan fokus, jadi letakkannya dengan sewajarnya.

Ia berwarna supaya mudah dilihat bahawa ia berada dalam fokus.

Buat masa ini, jika anda menjalankannya dalam keadaan ini, anda dapat melihat bahawa jika anda mengklik tempat kosong selepas objek menerima tumpuan, ia akan kehilangan tumpuan.

Kawal supaya anda tidak hilang fokus

Untuk melakukan ini, buat skrip. Nama skrip boleh menjadi apa-apa, tetapi FocusRequired biarkan sebagai .

Masukkan kod seperti 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 terlalu terperinci, tetapi Apa yang saya lakukan ialah mengekalkan objek pemilihan semasa, dan jika "objek yang dipilih hilang" atau "Saya telah memilih objek yang saya tidak mahu dipilih", saya kembali kepada pemilihan sebelumnya.

Komponen ini boleh dilampirkan pada mana-mana objek yang wujud, jadi EventSystem pasangkannya kepada .

Oleh kerana adalah mungkin untuk menentukan objek yang anda tidak mahu dipilih sebagai harta, mari cuba letakkan butang yang anda tidak mahu pilih.

Not Selectables butang ditetapkan kepada .

Cuba jalankannya untuk melihat bagaimana ia berfungsi. Mula-mula, klik pada objek untuk memilihnya, kemudian klik pada kawasan kosong supaya ia tidak kehilangan fokus.

Anda juga boleh memastikan bahawa mengklik butang yang ditetapkan untuk tidak dipilih tidak mengalihkan fokus.