Holde fokus ude af brugergrænsefladeobjektet

Side opdateret :
Dato for oprettelse af side :

Miljø til bekræftelse

Windows
  • Windows 11
Enhedslistens redaktør
  • 2020.3.25f1

Forudsætninger for dette tip

Følgende indstillinger er foretaget på forhånd som en forudsætning for forklaringen af disse tip.

Hvad fandt du nyttigt i dette tip?

Den oprindelige historie var et sted, men jeg kunne ikke finde den ved at søge efter nøgleord.

Om Focus

Unity UI-objekter kan ligesom enhver anden app have et fokus, der angiver, at de er aktive som inputmål. Men hvis du klikker eller rører ved noget andet end objektet, forsvinder objektet med fokus. Det er muligvis ikke muligt at acceptere handlinger med et tastatur eller en gamepad.

I dette afsnit beskrives, hvordan du bruger scripting til at styre fokus, så det ikke mister fokus i en pseudo. Bemærk, at denne support ikke er en Unity-funktion og kan få dig til at miste fokus et øjeblik.

Placering af objekter

Objekttypen betyder ikke noget i fokuskontrol, så placer den korrekt.

Den er farvet, så det er let at se, at den er i fokus.

For øjeblikket, hvis du kører det i denne tilstand, kan du se, at hvis du klikker på et tomt sted, efter at objektet har fået fokus, mister det fokus.

Kontrol, så du ikke mister fokus

For at gøre dette skal du oprette et script. Scriptnavnet kan være hvad som helst, men FocusRequired lad det være som .

Indtast koden som følger:

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

Jeg vil ikke gå for meget i detaljer, men Det, jeg gør, er at beholde det aktuelle markeringsobjekt, og hvis "det markerede objekt er væk" eller "Jeg har valgt et objekt, som jeg ikke vil markere", vender jeg tilbage til det forrige valg.

Denne komponent kan knyttes til ethvert objekt, der findes, så EventSystem vedhæft den til .

Da det er muligt at angive det objekt, som du ikke ønsker at blive valgt som en egenskab, lad os prøve at placere en knap, som du ikke vil vælge.

Not Selectables knappen er indstillet til .

Prøv at køre det for at se, hvordan det fungerer. Klik først på et objekt for at vælge det, og klik derefter på et tomt område, så det ikke mister fokus.

Du kan også sikre dig, at et klik på en knap, der er indstillet til ikke at være valgt, ikke flytter fokus.