Garder le focus en dehors de l’objet de l’interface utilisateur

Page mise à jour :
Date de création de la page :

Environnement de vérification

Windows
  • Fenêtres 11
Éditeur Unity
  • 2020.3.25f1

Conditions préalables à cette astuce

Les réglages suivants ont été effectués à l’avance comme condition préalable à l’explication de ces conseils.

Qu’avez-vous trouvé utile dans cette astuce ?

L’histoire originale était quelque part, mais je n’ai pas pu la trouver en cherchant des mots-clés.

À propos de Focus

Les objets de l’interface utilisateur Unity, comme toute autre application, peuvent avoir un focus qui indique qu’ils sont actifs en tant que cibles d’entrée. Toutefois, si vous cliquez ou touchez autre chose que l’objet, l’objet sélectionné disparaît. Il se peut qu’il ne soit pas possible d’accepter des opérations avec un clavier ou une manette de jeu.

Cette section décrit comment utiliser les scripts pour contrôler le focus afin qu’il ne perde pas le focus dans un pseudo. Notez que cette prise en charge n’est pas une fonctionnalité Unity et peut vous faire perdre votre concentration pendant un moment.

Placement d’objets

Le type d’objet n’a pas d’importance dans le contrôle de la mise au point, alors placez-le de manière appropriée.

Il est coloré de manière à ce qu’il soit facile de voir qu’il est net.

Pour l’instant, si vous l’exécutez dans cet état, vous pouvez voir que si vous cliquez sur un endroit vide après que l’objet ait reçu le focus, il perdra le focus.

Contrôle pour ne pas perdre sa concentration

Pour ce faire, créez un script. Le nom du script peut être n’importe quoi, mais FocusRequired laissez-le sous la forme .

Entrez le code comme suit :

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

Je n’entrerai pas trop dans les détails, mais Ce que je fais, c’est conserver l’objet de sélection actuel, et si « l’objet sélectionné a disparu » ou « j’ai sélectionné un objet que je ne veux pas sélectionner », je reviens à la sélection précédente.

Ce composant peut être attaché à n’importe quel objet existant, alors EventSystem attachez-le à .

Puisqu’il est possible de spécifier l’objet que vous ne souhaitez pas sélectionner en tant que propriété, essayons de placer un bouton que vous ne souhaitez pas sélectionner.

Not Selectables est réglé sur .

Essayez de l’exécuter pour voir comment cela fonctionne. Tout d’abord, cliquez sur un objet pour le sélectionner, puis cliquez sur une zone vide afin qu’il ne perde pas le focus.

Vous pouvez également vous assurer que le fait de cliquer sur un bouton dont la sélection est définie ne déplace pas le focus.