Mantenere lo stato attivo fuori dall'oggetto dell'interfaccia utente

Pagina aggiornata :
Data di creazione della pagina :

Ambiente di verifica

Finestre
  • finestre 11
Unity Editor
  • 2020.3.25f1

Prerequisiti per questo suggerimento

Le seguenti impostazioni sono state effettuate in anticipo come prerequisito per la spiegazione di questi suggerimenti.

Cosa hai trovato utile in questo suggerimento?

La storia originale era da qualche parte, ma non sono riuscito a trovarla cercando parole chiave.

Informazioni su Focus

Gli oggetti dell'interfaccia utente di Unity, come qualsiasi altra app, possono avere uno stato attivo che indica che sono attivi come destinazioni di input. Tuttavia, se si fa clic o si tocca un oggetto diverso dall'oggetto, l'oggetto con lo stato attivo scomparirà. Potrebbe non essere possibile accettare operazioni con una tastiera o un gamepad.

In questa sezione viene descritto come utilizzare lo scripting per controllare lo stato attivo in modo che non perda lo stato attivo in uno pseudo. Si noti che questo supporto non è una funzionalità di Unity e potrebbe causare la perdita di messa a fuoco per un momento.

Posizionamento degli oggetti

Il tipo di oggetto non ha importanza nel controllo della messa a fuoco, quindi posizionalo in modo appropriato.

È colorato in modo che sia facile vedere che è a fuoco.

Per il momento, se lo esegui in questo stato, puoi vedere che se fai clic su un punto vuoto dopo che l'oggetto ha ricevuto lo stato attivo, perderà lo stato attivo.

Controlla per non perdere la concentrazione

A tale scopo, creare uno script. Il nome dello script può essere qualsiasi cosa, ma FocusRequired lascialo come .

Inserisci il codice come segue:

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

Non entrerò troppo nei dettagli, ma Quello che sto facendo è mantenere l'oggetto di selezione corrente, e se "l'oggetto selezionato è sparito" o "ho selezionato un oggetto che non voglio venga selezionato", sto tornando alla selezione precedente.

Questo componente può essere collegato a qualsiasi oggetto esistente, quindi EventSystem collegarlo a .

Poiché è possibile specificare l'oggetto che non si desidera selezionare come proprietà, provare a posizionare un pulsante che non si desidera selezionare.

Not Selectables il pulsante è impostato su .

Prova a eseguirlo per vedere come funziona. Innanzitutto, fai clic su un oggetto per selezionarlo, quindi fai clic su un'area vuota in modo che non perda la messa a fuoco.

È inoltre possibile assicurarsi che facendo clic su un pulsante impostato per non essere selezionato non si sposti lo stato attivo.