Odağı UI nesnesinin dışında tutma

Sayfa güncel :
Sayfa oluşturma tarihi :

Doğrulama ortamı

Windows
  • pencereler 11
Unity Düzenleyicisi
  • 2020.3.25f1

Bu ipucu için önkoşullar

Bu ipuçlarının açıklanması için ön koşul olarak aşağıdaki ayarlar önceden yapılmıştır.

Bu ipucunda neyi yararlı buldunuz?

Orijinal hikaye bir yerlerdeydi, ancak anahtar kelimeleri arayarak bulamadım.

Focus Hakkında

Unity UI nesneleri, diğer tüm uygulamalar gibi, giriş hedefleri olarak etkin olduklarını gösteren bir odağa sahip olabilir. Ancak, nesneden başka bir şeye tıklar veya dokunursanız, odağı olan nesne kaybolur. Klavye veya gamepad ile işlem kabul etmek mümkün olmayabilir.

Bu bölümde, sözde bir odakta odağı kaybetmemesi için odağı kontrol etmek için komut dosyasının nasıl kullanılacağı açıklanmaktadır. Bu desteğin bir Unity özelliği olmadığını ve bir an için odağınızı kaybetmenize neden olabileceğini unutmayın.

Nesne Yerleştirme

Odak kontrolünde nesnenin türü önemli değildir, bu nedenle uygun şekilde yerleştirin.

Odakta olduğunu kolayca görebilecek şekilde renklendirilmiştir.

Şimdilik, bu durumda çalıştırırsanız, nesne odağı aldıktan sonra boş bir yere tıklarsanız, odağı kaybedeceğini görebilirsiniz.

Odağınızı kaybetmemek için kontrol edin

Bunu yapmak için bir komut dosyası oluşturun. Komut dosyası adı herhangi bir şey olabilir, ancak FocusRequired olarak bırakın.

Kodu aşağıdaki gibi girin:

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

Çok fazla ayrıntıya girmeyeceğim ama Yaptığım şey mevcut seçim nesnesini korumak ve "seçilen nesne gitti" veya "seçilmesini istemediğim bir nesne seçtim" ise, önceki seçime geri dönüyorum.

Bu bileşen var olan herhangi bir nesneye eklenebilir, bu nedenle EventSystem öğesine ekleyin.

Seçilmesini istemediğiniz nesneyi özellik olarak belirtmeniz mümkün olduğundan, seçmek istemediğiniz bir buton yerleştirmeyi deneyelim.

Not Selectables düğmesi olarak ayarlanır.

Nasıl çalıştığını görmek için çalıştırmayı deneyin. Önce seçmek için bir nesneye tıklayın ve ardından odağını kaybetmemesi için boş bir alana tıklayın.

Seçili değil olarak ayarlanmış bir düğmeyi tıklattığınızda odağı hareket ettirmediğinden de emin olabilirsiniz.