Кастомизация
Собственная реализация портов
Общее
Для создания собственной реализации:
- Наследуйтесь от
PassageBaseилиTeleportBase, либо реализуйтеITransitionComponent; - Используйте класс PortsDropdown и соответствующие методы в
RefreshContextилиEditorGraphдля создания выпадающих списков для инициализации текущего порта или выбора любого порта на графе; - Реализуйте метод
GetGuid(), возвращающийGuidтекущего порта; - В редакторе реализуйте
Refresh(RefreshContext context)— полное описание методов контекста см. вRefreshContext.
PassageBase, TeleportBase и ITransitionComponent
PassageBase и TeleportBase — абстрактные базовые классы для прохода и телепорта: в них уже проведена работа с PortsDropdown и полями. Для большинства случаев достаточно наследоваться от одного из них и переопределить нужные методы (например, GetSpawnPosition()).
ITransitionComponent — минимальный контракт «порт на сцене»:
string GetGuid()— идентификатор порта в графе.Vector3 GetSpawnPosition()— позиция появления персонажа у этого порта.
Дополнительно в редакторе ожидается метод void Refresh(RefreshContext context) — см. RefreshContext.
Если не подходят готовые базовые классы, можно реализовать только ITransitionComponent и написать логику самостоятельно (см. примеры).
Метод Refresh() рекомендуется обернуть в #if UNITY_EDITOR, так как он нужен только в редакторе.
Методы расширения
Для ITransitionComponent так же предусмотрены методы расширения.
IsInput(manager) и IsOutput(manager) позволяют узнать, является ли текущий компонент начальным или конечным для перехода (через который персонаж вошел/вышел). Менеджер передаётся явно, поэтому методы одинаково работают как со встроенным, так и с собственным TransitionManager.
| Метод | Назначение |
|---|---|
IsOutput(manager) | true если это компонент, в котором закончен переход. |
IsInput(manager) | true если это компонент, из которого начат переход. |
Перегрузки без параметра (IsOutput(), IsInput()) помечены [Obsolete] и используют TransitionManager.Instance. Если в проекте включён собственный TransitionManager, они выбросят исключение — используйте перегрузки с явным manager.
IsShortcutOrigin() и IsShortcutDestination() позволяют узнать, является ли текущий компонент для shortcut-связи между сценами входным или выходным. Аналогично IsOneWayOrigin() и IsOneWayDestination() — для one-way-связей. Эти методы не требуют менеджера и читают граф напрямую.
| Метод | Назначение |
|---|---|
IsShortcutDestination() | true если компонент является "выходным" для shortcut |
IsShortcutOrigin() | true если компонент является "входным" для shortcut |
IsOneWayDestination() | true если компонент является "выходным" для one-way |
IsOneWayOrigin() | true если компонент является "входным" для one-way |
Если тип связи не совпадает (например, вызвать IsShortcutOrigin() для one-way связи) - метод вернёт false.
RefreshContext
RefreshContext — структура, которую редактор передаёт в метод void Refresh(RefreshContext context) у компонентов с интерфейсом ITransitionComponent. Используется только в редакторе. При смене сцены, иерархии и обновлениях графа вызывается Refresh, чтобы подтянуть актуальные Guid портов в PortsDropdown и связанные поля.
Поля:
| Имя | Тип | Описание |
|---|---|---|
EditorGraph | EditorGraph | Граф текущего контейнера. Используется для ручного доступа к данным, если не хватает методов ниже. |
Методы:
| Метод | Назначение |
|---|---|
void FillPortsDropdownData(PortsDropdown dropdown) | Заполняет список портами активной сцены. |
void FillAllPortsDropdownData(PortsDropdown dropdown) | Заполняет список всеми портами графа из контейнера. |
Методы переходов в TransitionManager
Task LoadSceneAsync(int buildIndex, TransitionContext context = null)
Загружает сцену по переданному индексу.
Параметры:
| Имя | Тип | Описание |
|---|---|---|
buildIndex | int | Build Index сцены. |
context | TransitionContext | Опциональные параметры задержки между фазами перехода. |
Task GoFromAsync(string currentPortGuid, bool ignoreShortcuts, ITransitionContext context = null)
Перемещает игрока к противоположному порту, опираясь на связи в графе.
Параметры:
| Имя | Тип | Описание |
|---|---|---|
currentPortGuid | string | Guid текущего порта. |
ignoreShortcuts | bool | Игнорировать ли шорткаты. |
context | ITransitionContext | Встроенный TransitionManager работает только с объектом TransitionContext, позволяющий задавать параметры задержки между фазами перехода. |
Task GoToAsync(string currentPortGuid, string targetPortGuid, TransitionContext context = null)
Перемещает игрока на любой выбранный порт. Не опирается на связи в графе.
Параметры:
| Имя | Тип | Описание |
|---|---|---|
currentPortGuid | string | Guid текущего порта |
targetPortGuid | string | Guid целевого порта |
context | ITransitionContext | Встроенный TransitionManager работает только с объектом TransitionContext, позволяющий задавать параметры задержки между фазами перехода. |
Методы GoToAsync / GoFromAsync / LoadSceneAsync возвращают Task — их можно ожидать через await. Для вызова без ожидания (fire-and-forget) используйте _ = TransitionManager.Instance.GoFromAsync(...). Старые синхронные методы GoTo / GoFrom / LoadScene помечены [Obsolete]. У встроенного менеджера также есть перегрузка GoFromAsync(currentPortGuid, context) без ignoreShortcuts — как в интерфейсе ITransitionManager.
Примеры GoToAsync/GoFromAsync
Пример минимальной рабочей реализации собственного прохода с помощью GoFromAsync:
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class ExamplePassage : MonoBehaviour, ITransitionComponent
{
[SerializeField] private PortsDropdown _assignedPort = new();
private string _currentGuid;
// Любой вызов, например при входе в триггер
private void OnTriggerEnter(Collider other)
{
// Вызов GoFromAsync
_ = TransitionManager.Instance.GoFromAsync(_currentGuid);
}
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
context.FillPortsDropdownData(_assignedPort);
_currentGuid = _assignedPort.GetSelectedValue();
}
#endif
public Vector3 GetSpawnPosition() => transform.position;
public string GetGuid() => _currentGuid;
}
}
Пример минимальной рабочей реализации собственного телепорта с помощью GoToAsync:
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class ExampleTeleport : MonoBehaviour, ITransitionComponent
{
[SerializeField] private PortsDropdown _assignedPort = new();
[SerializeField] private PortsDropdown _targetPort = new();
private string _currentGuid;
private string _targetGuid;
// Любой вызов, например при входе в триггер
private void OnTriggerEnter(Collider other)
{
// Вызов GoToAsync
_ = TransitionManager.Instance.GoToAsync(_currentGuid, _targetGuid);
}
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
context.FillPortsDropdownData(_assignedPort);
context.FillAllPortsDropdownData(_targetPort);
_currentGuid = _assignedPort.GetSelectedValue();
_targetGuid = _targetPort.GetSelectedValue();
}
#endif
public Vector3 GetSpawnPosition() => transform.position;
public string GetGuid() => _currentGuid;
}
}
TransitionContext
TransitionContext — это класс, позволяющий переопределить задержку между фазами для текущего перехода. Может быть передан в качестве дополнительного параметра в GoToAsync, GoFromAsync и LoadSceneAsync.
Пример
_ = TransitionManager.Instance.GoFromAsync(_port.GetSelectedValue(), true,
new TransitionContext
{
PortEnteredDelay = new TransitionDelayData(DelayType.ThisFrame),
TransitionStartedDelay = new TransitionDelayData(DelayType.CustomDelay, 1.2f)
});
PortsDropdown
PortsDropdown — это класс, предназначенный для создания выпадающих списков, связанных с портами в графе. Он обеспечивает сохранность выбранного значения даже при переименовании портов или изменении их количества на ноде.
Содержит два метода:
string GetSelectedValue()
Возвращаемые значения:
| Тип | Описание |
|---|---|
string | Выбранное значение (Guid) |
void SetData(IEnumerable<(string Guid, string DisplayName)> data)
Обновляет данные для выпадающего списка, состоящие из Guid и отображаемого имени.
Параметры:
| Имя | Тип | Описание |
|---|---|---|
data | IEnumerable<(string Guid, string DisplayName)> | Данные, где каждый элемент содержитGuid и имя для отображения |
Низкоуровневый доступ: EditorGraph и PortsDropdown
В типичном сценарии для заполнения PortsDropdown данными из графа в Refresh(RefreshContext context) достаточно вызвать context.FillPortsDropdownData(dropdown) или context.FillAllPortsDropdownData(dropdown) — см. RefreshContext.
Ниже описаны методы EditorGraph (доступен через context.EditorGraph или WorldGraphContainer.EditorGraph): они возвращают сырые последовательности для SetData, если нужна фильтрация, объединение с другими данными или иная кастомная сборка списка. Полная поверхность EditorGraph — в API: IWorldGraph, WorldGraph и EditorGraph.
Использование только в редакторе.
IEnumerable<(string Guid, string Name)> GetPortsDropdownData(string scenePath)
Параметры:
| Имя | Тип | Описание |
|---|---|---|
scenePath | string | Путь к ассету сцены (файл .unity), как у Scene.path. |
Возвращаемые значения:
| Тип | Описание |
|---|---|
IEnumerable<(string Guid, string Name)> | Данные обо всех портах на сцене. Их Guid и отображаемое имя |
Пример
Рекомендуемый способ — через RefreshContext:
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class MyComponentWithDropdown : MonoBehaviour, ITransitionComponent
{
[SerializeField] private PortsDropdown _dropdown = new();
private string _currentPortGuid;
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
context.FillPortsDropdownData(_dropdown);
_currentPortGuid = _dropdown.GetSelectedValue();
}
#endif
// public Vector3 GetSpawnPosition() {}
// public string GetGuid() {}
}
}
Вариант через EditorGraph:
using UnityEngine;
using UnityEngine.SceneManagement;
namespace WorldGraphEditor.Examples
{
public class MyComponentWithDropdown : MonoBehaviour, ITransitionComponent
{
[SerializeField] private PortsDropdown _dropdown = new();
private string _currentPortGuid;
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
var scenePath = SceneManager.GetActiveScene().path;
var scenePortsData = context.EditorGraph.GetPortsDropdownData(scenePath);
_dropdown.SetData(scenePortsData);
_currentPortGuid = _dropdown.GetSelectedValue();
}
#endif
// public Vector3 GetSpawnPosition() {}
// public string GetGuid() {}
}
}
Перегрузка GetPortsDropdownData(int buildIndex) помечена как [Obsolete]. Предпочтительно использовать вариант с scenePath, чтобы не зависеть от порядка сцен в Build Settings.
IEnumerable<(string Guid, string Path)> GetAllPortsDropdownData()
Возвращает данные обо всех портах на графе, группируя их по сценам.
Возвращаемые значения:
| Тип | Описание |
|---|---|
IEnumerable<(string Guid, string Path)> | Данные обо всех портах на графе |
Пример
Рекомендуемый способ — через RefreshContext:
using System;
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class MyComponentWithDropdown : MonoBehaviour, ITransitionComponent
{
[SerializeField] private PortsDropdown _dropdown = new();
private string _currentPortGuid;
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
context.FillAllPortsDropdownData(_dropdown);
_currentPortGuid = _dropdown.GetSelectedValue();
}
#endif
// public Vector3 GetSpawnPosition() {}
// public string GetGuid() {}
}
}
Вариант через EditorGraph:
using System;
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class MyComponentWithDropdown : MonoBehaviour, ITransitionComponent
{
// Выпадающий список
[SerializeField] private PortsDropdown _dropdown = new();
private string _currentPortGuid;
#if UNITY_EDITOR
public void Refresh(RefreshContext context)
{
var allPortsData = context.EditorGraph.GetAllPortsDropdownData();
_dropdown.SetData(allPortsData);
_currentPortGuid = _dropdown.GetSelectedValue();
}
#endif
// public Vector3 GetSpawnPosition() {}
// public string GetGuid() {}
}
}
Выталкивание из проходов
Вы можете добавить "силу выталкивания" для порта, реализовав интерфейс IPusher и метод GetPushData(), возвращающий PushData.
PushData это структура, содержащая в себе два поля:
Force— Сила выталкиванияExists— Указывает, существует сила или нет
public readonly struct PushData {
public readonly Vector3 Force;
public readonly bool Exists;
public PushData(Vector3 force)
{
Force = force;
Exists = true;
}
}
Пример
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class MyPushingPassage : PassageBase, IPusher
{
[SerializeField] private Vector2 _pushForce;
public PushData GetPushData()
{
// Если сила (0, 0), то можно вернуть PushData со значениями по умолчанию
if (_pushForce == Vector2.zero)
// Возвращает значение по умолчанию, где Exists будет false
return default;
// Если сила есть, то ее можно передать в конструктор. Exists в таком случае станет true
return new PushData(_pushForce);
}
// Прочие методы
//...
}
}
Чтобы применить эту силу к объекту игрока, используйте TransitionManager.Instance.PushData для получения актуального значения.
Пример
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class PlayerController : MonoBehaviour
{
[SerializeField] private Rigidbody2D _rigidbody;
private void OnTransitionEnded()
{
// Получение силы выталкивания
var pushData = TransitionManager.Instance.PushData;
// Применение силы к Rigidbody только если она существует
if (pushData.Exists)
_rigidbody.AddForce(pushData.Force, ForceMode2D.Impulse);
}
private void Awake()
{
TransitionManager.Instance.TransitionEnded += OnTransitionEnded;
}
private void OnDestroy()
{
TransitionManager.Instance.TransitionEnded -= OnTransitionEnded;
}
}
}
Замена встроенного TransitionManager
По умолчанию используется встроенный TransitionManager, но вы можете полностью заменить его своей реализацией — например, для интеграции с DI-фреймворком (Zenject, VContainer и т.п.) или для другой архитектуры загрузки сцен.
Включение
- Откройте Edit → Project Settings → World Graph Editor (см. Настройки проекта);
- Включите чекбокс Use Custom Transition Manager;
- В появившемся поле Container укажите тот же
WorldGraphContainer, что используется в графе.
После включения этого чекбокса встроенный TransitionManager не создаётся автоматически при старте игры. Инициализацию менеджера в этом случае полностью берёт на себя ваш код (например, DI-контейнер).
Интерфейс ITransitionManager
public interface ITransitionManager
{
public IWorldGraph Graph { get; }
public Vector3 NextSpawnPosition { get; }
public ITransitionComponent? OutputTransitionComponent { get; }
public ITransitionComponent? InputTransitionComponent { get; }
public event Action TransitionStarted;
public event Action SceneLoaded;
public event Action TransitionEnded;
public Task GoToAsync(string currentPortGuid, string targetPortGuid, ITransitionContext context = null);
public Task GoFromAsync(string currentPortGuid, ITransitionContext context = null);
}
Graph— рантайм-граф контейнера; получить его можно черезWGEProjectConfig.Instance.GetWorldGraph().OutputTransitionComponent/InputTransitionComponent— порты, между которыми происходит текущий или последний переход. Используются методами расширенияIsOutput(manager)/IsInput(manager)(см. Методы расширения).GoToAsync/GoFromAsync— асинхронные точки входа для запуска перехода:GoToAsync— телепорт между двумя произвольными портами,GoFromAsync— переход из текущего порта по связи в графе. Оба метода возвращаютTask; флагignoreShortcutsиз интерфейса убран — допустимость перехода определяет сама реализацияITransitionManager.
Для поиска и перемещения по графу у IWorldGraph (реализация — класс WorldGraph, наследующий GraphEngine) доступны методы CanPassTransition(guid, ignoreShortcuts, out status), TryGetPassageTransitionData(guid, out data), GetTeleportTransitionData(currentGuid, targetGuid), TryGetOppositePassageGuid и другие — полная таблица в API: IWorldGraph, WorldGraph и EditorGraph. Чтобы найти компонент порта на загруженной сцене, используйте TransitionComponentUtility.FindByGuid(portGuid).
При включённом собственном менеджере методы-расширения IsOutput() / IsInput() без параметра выбросят исключение — используйте IsOutput(manager) / IsInput(manager), передавая свой экземпляр ITransitionManager (см. Методы расширения).
Пример: реализация на Zenject
Готовый демо-проект, показывающий реализацию ITransitionManager через DI, доступен по ссылке.
Регистрация графа и сервиса в контейнере:
public class TransitionManagerProjectInstaller : MonoInstaller
{
public override void InstallBindings()
{
var graph = WGEProjectConfig.Instance.GetWorldGraph();
Container.BindInterfacesAndSelfTo<WorldGraph>().FromInstance(graph)
.AsSingle();
Container.BindInterfacesAndSelfTo<TransitionManagerService>()
.AsSingle();
}
}
Сам сервис (TransitionManagerService) получает IWorldGraph через конструктор и реализует переход через смену сцены:
public class TransitionManagerService : ITransitionManager
{
public IWorldGraph Graph { get; }
public ITransitionComponent OutputTransitionComponent { get; private set; }
public ITransitionComponent InputTransitionComponent { get; private set; }
public event Action TransitionStarted;
public event Action SceneLoaded;
public event Action TransitionEnded;
public Vector3 NextSpawnPosition { get; private set; }
public TransitionManagerService(IWorldGraph graph)
{
Graph = graph;
}
public async Task GoFromAsync(string currentPortGuid, ITransitionContext context = null)
{
// Проверка что переход можно совершить
if (!Graph.CanPassTransition(currentPortGuid, false, out var status))
{
Debug.LogWarning($"Can`t pass transition, reason: {status}");
return;
}
// Для GoFromAsync используется метод TryGetPassageTransitionData
if (!Graph.TryGetPassageTransitionData(currentPortGuid, out var data))
{
Debug.LogError("No transition data for this passage");
return;
}
await GoInternal(data);
}
public async Task GoToAsync(string currentPortGuid, string targetPortGuid, ITransitionContext context = null)
{
// Для GoToAsync используется метод GetTeleportTransitionData
var data = Graph.GetTeleportTransitionData(currentPortGuid, targetPortGuid);
await GoInternal(data);
}
private async Task GoInternal(RuntimeTransitionData data)
{
TransitionStarted?.Invoke();
// Использование TransitionComponentUtility для поиска портов на сцене
InputTransitionComponent = TransitionComponentUtility
.FindByGuid(data.CurrentPassageGuid);
// Загрузка сцены по ее Build Index
await SceneManager.LoadSceneAsync(data.TargetSceneBuildIndex);
// Использование TransitionComponentUtility для поиска портов на сцене
OutputTransitionComponent = TransitionComponentUtility
.FindByGuid(data.TargetPassageGuid);
NextSpawnPosition = OutputTransitionComponent?
.GetSpawnPosition() ?? Vector3.zero;
SceneLoaded?.Invoke();
TransitionEnded?.Invoke();
}
}
Поскольку метод GoFromAsync не принимает ignoreShortcuts, при необходимости, можно воспользоваться ITransitionContext и передать параметр через него:
public class IgnoreShortcutsContext : ITransitionContext
{
public bool IgnoreShortcuts { get; }
private IgnoreShortcutsContext(bool ignoreShortcuts)
{
IgnoreShortcuts = ignoreShortcuts;
}
public static ITransitionContext Ignore => new IgnoreShortcutsContext(true);
public static ITransitionContext Respect => new IgnoreShortcutsContext(false);
}
Обработка в TransitionManagerService:
public async Task GoFromAsync(string currentPortGuid, ITransitionContext context = null)
{
var ignoreShortcuts = context is IgnoreShortcutsContext passContext && passContext.IgnoreShortcuts;
if (!Graph.CanPassTransition(currentPortGuid, ignoreShortcuts, out var status))
{
// ...
}
// ...
}
Вызов из ITransitionComponent:
public void Traverse()
{
// (true)
_manager.GoFromAsync(GetGuid(), IgnoreShortcutsContext.Ignore);
// (false)
_manager.GoFromAsync(GetGuid(), IgnoreShortcutsContext.Respect);
// (false)
_manager.GoFromAsync(GetGuid());
}
TransitionComponentUtility
Для поиска ITransitionComponent или его реализаций на сцене должен использоваться класс TransitionComponentUtility. Это необходимо, поскольку внутри себя методы FindByGuid(string) и FindByGuid<T>(string) заодно вызывают Refresh() на каждом переборном компоненте, чтобы их guid были актуальны на момент сравнения.
Методы:
| Метод | Описание |
|---|---|
ITransitionComponent FindAny() | Возвращает первый попавшийся ITransitionComponent на сцене. |
T FindAny<T>() | Возвращает первый попавшийся T, реализующий ITransitionComponent на сцене. |
ITransitionComponent FindByGuid(string) | Возвращает ITransitionComponent по переданному guid. |
T FindByGuid<T>(string) | Возвращает T, реализующий ITransitionComponent по переданному guid. |
Ручной запуск встроенного TransitionManager
По умолчанию TransitionManager запускается автоматически при старте игры, однако вы можете создать его в удобный для вас момент.
Отключение автозагрузки
- Установите
AutoLoadвfalse - Чтобы создать менеджер, вызовите
TransitionManager.CreateInstance()
Пример
using UnityEngine;
namespace WorldGraphEditor.Examples
{
public class MyTransitionManagerLoader : MonoBehaviour
{
[SerializeField] private float _loadDelay = 2f;
private void Start()
{
Invoke(nameof(MyLoadMethod), _loadDelay);
}
private void MyLoadMethod()
{
// Создание менеджера
TransitionManager.CreateInstance();
}
}
}
TransitionManager так же содержит в себе метод LoadFromResources(), однако он лишь возвращает экземпляр класса из папки Resources и не создает объект в DontDestroyOnLoad. В первую очередь этот метод используется в режиме редактора для получения ссылки. Рекомендуется использовать именно CreateInstance(), поскольку в нем предусмотрена защита от создания нескольких экземпляров класса.
События и вызов асинхронного кода
Встроенный TransitionManager обладает событиями, которые оповещают о текущих фазах перехода:
- Initialized: Вызывается после успешной инициализации
TransitionManager; - Destroyed: Вызывается в
OnDestroy()вTransitionManager; - PortEntered: Вызывается при вызове
GoFromAsync()илиGoToAsync(); - TransitionStarted: Вызывается перед началом загрузки следующей сцены;
- SceneLoaded: Вызывается после загрузки сцены и после того, как был найден "выходной порт"
OutputTransitionComponentа так же, определена позиция появления игрокаNextSpawnPosition; - TransitionEnded: Вызывается после создания префаба игрока. Если префаб не был указан, событие все равно будет вызвано;
- PortLeaved: Вызывается после
OnTransitionEnded.
Задержка между фазами перехода
Вы можете задать задержку между фазами перехода перед вызовом асинхронных методов с помощью EventCallConfig:
- Создание
- ПКМ → Create → World Graph Editor → Event Call Config.
- Укажите один из доступных видов задержки:
- This Frame — В текущем кадре;
- Next Frame — В следующем кадре;
- Physics Update — В
FixedUpdate(); - Custom Delay — Через заданное время.
- Перетащите
EventCallConfigв соответствующее полеTransitionManager.
Ожидание завершения асинхронных методов
Если нужно дождаться выполнения операций, таких, как генерация уровня, вы можете зарегистрировать асинхронные методы с учётом их приоритета с помощью TransitionManager.RegisterAsyncHandler(). Чем выше значение приоритета, тем раньше метод будет вызван.
Таким образом, порядок вызова при каждой фазе перехода будет таким:
- Вызов события перехода (OnPortEntered / OnTransitionStarted / OnSceneLoaded / OnTransitionEnded);
- Ожидание задержки
EventCallConfig; - Ожидание выполнения асинхронных методов.
Тип события, после которого начинается выполнение зарегистрированных асинхронных методов, указывается с помощью перечисления EventType.
События, для которых можно зарегистрировать асинхронные методы:
public enum EventType
{
OnPortEntered,
OnTransitionStarted,
OnSceneLoaded,
OnTransitionEnded,
}
Работа с асинхронными методами
static void RegisterAsyncHandler(EventType eventType, Func<CancellationToken, Task> func, int priority)
Параметры:
| Имя | Тип | Описание |
|---|---|---|
eventType | EventType | Тип события, после которого должен начаться вызов асинхронных методов. |
func | Func<CancellationToken, Task> | Асинхронный метод, который принимает CancellationToken и возвращает Task. |
priority | int | Приоритет вызова метода. |
static void UnregisterAsyncHandler(EventType eventType, Func<CancellationToken, Task> func)
Параметры:
| Имя | Тип | Описание |
|---|---|---|
eventType | EventType | Тип события, для которого нужно удалить метод |
func | Func<CancellationToken, Task> | Асинхронный метод, который принимает CancellationToken и возвращает Task |
Встроенный TransitionManager в методе OnDestroy автоматически вызывает CancellationTokenSource.Cancel(), а так же удаляет все зарегистрированные в нем методы.
Пример
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
namespace WorldGraphEditor.Examples
{
public class AsyncAfterSceneLoadedExample : MonoBehaviour
{
private readonly EventType _event = EventType.OnSceneLoaded;
private void Awake()
{
TransitionManager.RegisterAsyncHandler(Event, RunAfterSceneLoaded, 0);
}
private async Task RunAfterSceneLoaded(CancellationToken token)
{
await Awaitable.WaitForSecondsAsync(0.25f, token);
}
private void OnDisable()
{
TransitionManager.UnregisterAsyncHandler(Event, RunAfterSceneLoaded);
}
}
}