Hålla fokus borta från användargränssnittsobjektet

Sidan uppdaterad :
Datum för skapande av sida :

Miljö för verifiering

Windows
  • Windows 11 (på engelska)
Unity-redigeraren
  • 2020.3.25f1

Förutsättningar för det här tipset

Följande inställningar har gjorts i förväg som en förutsättning för förklaringen av dessa tips.

Vad tyckte du var användbart i det här tipset?

Den ursprungliga berättelsen fanns någonstans, men jag kunde inte hitta den genom att söka efter nyckelord.

Om Focus

Unity-gränssnittsobjekt kan, precis som andra appar, ha ett fokus som anger att de är aktiva som indatamål. Men om du klickar eller trycker på något annat än objektet försvinner objektet med fokus. Det kanske inte går att acceptera åtgärder med ett tangentbord eller en gamepad.

I det här avsnittet beskrivs hur du använder skript för att styra fokus så att det inte tappar fokus i en pseudo. Observera att det här stödet inte är en Unity-funktion och kan leda till att du tappar fokus en stund.

Placering av objekt

Typen av objekt spelar ingen roll i fokuskontroll, så placera den på lämpligt sätt.

Den är färgad så att det är lätt att se att den är i fokus.

För tillfället, om du kör det i det här tillståndet, kan du se att om du klickar på en tom plats efter att objektet har fått fokus, kommer det att tappa fokus.

Styr så att du inte tappar fokus

Det gör du genom att skapa ett skript. Skriptnamnet kan vara vad som helst, men FocusRequired lämna det som .

Ange koden enligt följande:

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

Jag kommer inte att gå in på för mycket detaljer, men Vad jag gör är att behålla det aktuella markeringsobjektet, och om "det markerade objektet är borta" eller "Jag har markerat ett objekt som jag inte vill ska markeras", återgår jag till det tidigare urvalet.

Den här komponenten kan kopplas till alla objekt som finns, så EventSystem koppla den till .

Eftersom det är möjligt att ange det objekt som du inte vill ska väljas som en egenskap, ska vi prova att placera en knapp som du inte vill markera.

Not Selectables knappen är inställd på .

Prova att köra den för att se hur den fungerar. Klicka först på ett objekt för att markera det och klicka sedan på ett tomt område så att det inte tappar fokus.

Du kan också se till att fokus inte flyttas när du klickar på en knapp som är inställd på att vara avmarkerad.