Udržiavanie zamerania mimo objektu používateľského rozhrania
Prostredie overovania
- Windows
-
- Windows 11
- Editor jednoty
-
- 2020.3.25f1
Predpoklady pre tento tip
Nasledujúce nastavenia boli vykonané vopred ako predpoklad pre vysvetlenie týchto tipov.
Čo považujete za užitočné v tomto tipe?
Pôvodný príbeh bol niekde, ale nemohol som ho nájsť hľadaním kľúčových slov.
O aplikácii Focus
Objekty používateľského rozhrania Unity, rovnako ako každá iná aplikácia, môžu mať zameranie, ktoré naznačuje, že sú aktívne ako vstupné ciele. Ak však kliknete alebo sa dotknete iného objektu než objektu, zaostrený objekt zmizne. Nemusí byť možné prijímať operácie pomocou klávesnice alebo gamepadu.
Táto časť popisuje, ako používať skriptovanie na ovládanie zamerania tak, aby nestratilo zameranie v pseudo. Upozorňujeme, že táto podpora nie je funkciou Unity a môže spôsobiť, že na chvíľu stratíte zameranie.
Umiestnenie objektu
Pri ovládaní zaostrenia nezáleží na type objektu, preto ho vhodne umiestnite.
Je farebný, takže je ľahké vidieť, že je zaostrený.
Zatiaľ, ak ho spustíte v tomto stave, môžete vidieť, že ak kliknete na prázdne miesto po tom, čo objekt dostane zaostrenie, stratí zaostrenie.
Ovládajte, aby ste nestratili zameranie
Ak to chcete urobiť, vytvorte skript. Názov skriptu môže byť čokoľvek, ale FocusRequired
nechajte ho ako .
Zadajte kód takto:
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);
}
}
}
Nebudem zachádzať do prílišných podrobností, ale To, čo robím, je zachovanie aktuálneho objektu výberu a ak "vybratý objekt je preč" alebo "Vybral som objekt, ktorý nechcem byť vybratý", vraciam sa k predchádzajúcemu výberu.
Tento komponent môže byť pripojený k akémukoľvek objektu, ktorý existuje, preto EventSystem
ho pripojte k .
Keďže je možné určiť objekt, ktorý nechcete vybrať ako vlastnosť, skúste umiestniť tlačidlo, ktoré nechcete vybrať.
Not Selectables
tlačidlo je nastavené na .
Skúste ho spustiť, aby ste zistili, ako to funguje. Najprv kliknite na objekt, aby ste ho vybrali, a potom kliknite na prázdnu oblasť, aby nestratil zaostrenie.
Môžete sa tiež uistiť, že kliknutím na tlačidlo, ktoré je nastavené ako nevybraté, sa výber nepresunie.