Giữ tiêu điểm ra khỏi đối tượng UI

Trang Cập Nhật :
Ngày tạo trang :

Môi trường xác minh

Windows
  • cửa sổ 11
Biên tập viên Unity
  • 2020.3.25f1

Điều kiện tiên quyết cho mẹo này

Các cài đặt sau đây đã được thực hiện trước như một điều kiện tiên quyết để giải thích các mẹo này.

Bạn thấy điều gì hữu ích trong mẹo này?

Câu chuyện gốc ở đâu đó, nhưng tôi không thể tìm thấy nó bằng cách tìm kiếm từ khóa.

Giới thiệu về Focus

Các đối tượng Unity UI, giống như bất kỳ ứng dụng nào khác, có thể có tiêu điểm cho biết rằng chúng đang hoạt động như các mục tiêu đầu vào. Tuy nhiên, nếu bạn nhấp hoặc chạm vào bất cứ thứ gì khác ngoài đối tượng, đối tượng được lấy nét sẽ biến mất. Có thể không chấp nhận được các thao tác bằng bàn phím hoặc gamepad.

Phần này mô tả cách sử dụng kịch bản để kiểm soát tiêu điểm để nó không bị mất nét trong một giả mạo. Lưu ý rằng hỗ trợ này không phải là tính năng Unity và có thể khiến bạn mất tập trung trong giây lát.

Vị trí đối tượng

Loại đối tượng không quan trọng trong điều khiển lấy nét, vì vậy hãy đặt nó một cách thích hợp.

Nó được tô màu để dễ dàng nhận thấy rằng nó được lấy nét.

Hiện tại, nếu bạn chạy nó ở trạng thái này, bạn có thể thấy rằng nếu bạn nhấp vào một vị trí trống sau khi đối tượng nhận được tiêu điểm, nó sẽ mất nét.

Kiểm soát để bạn không mất tập trung

Để làm điều này, tạo một kịch bản. Tên tập lệnh có thể là bất cứ thứ gì, nhưng FocusRequired hãy để nó là .

Nhập mã như sau:

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

Tôi sẽ không đi vào quá nhiều chi tiết, nhưng Những gì tôi đang làm là giữ đối tượng chọn hiện tại và nếu "đối tượng được chọn đã biến mất" hoặc "Tôi đã chọn một đối tượng mà tôi không muốn được chọn", tôi sẽ hoàn nguyên về lựa chọn trước đó.

Thành phần này có thể được gắn vào bất kỳ đối tượng nào tồn tại, vì vậy EventSystem hãy gắn nó vào .

Vì có thể chỉ định đối tượng mà bạn không muốn được chọn làm thuộc tính, hãy thử đặt một nút mà bạn không muốn chọn.

Not Selectables được đặt thành .

Hãy thử chạy nó để xem nó hoạt động như thế nào. Đầu tiên, nhấp vào một đối tượng để chọn nó, sau đó nhấp vào một vùng trống để nó không bị mất nét.

Bạn cũng có thể đảm bảo rằng việc bấm vào nút được đặt thành bỏ chọn không di chuyển tiêu điểm.