передавать данные через UnityEvent в архитектуре на основе событий - PullRequest
4 голосов
/ 06 октября 2019

Я исхожу из этой статьи

https://unity3d.com/how-to/architect-with-scriptable-objects

и хотел бы знать, как вызвать событие и передать в него данные. Потому что просто прослушивания этого события недостаточно. Я постараюсь объяснить это для воспроизведения.

Сначала я создал новое игровое событие LevelSceneLoadedGameEvent

class LevelSceneLoadedGameEvent : UnityEvent<Scene> { }

При поднятии этого события должно возвращаться текущая сцена, которая была загружена. Затем я создал статический EventManager для управления всеми этими событиями

public static class EventManager
{
    private static Dictionary<Type, UnityEvent> events = new Dictionary<Type, UnityEvent>()
    {
        {
            typeof(LevelSceneLoadedGameEvent),
            new LevelSceneLoadedGameEvent()
        }
    };

    private static UnityEvent GetEvent<EventType>() where EventType : UnityEvent
    {
        return events[typeof(EventType)];
    }

    public static void SubscribeTo<EventType>(UnityAction listener) where EventType : UnityEvent
    {
        GetEvent<EventType>().AddListener(listener);
    }

    public static void UnsubscribeFrom<EventType>(UnityAction listener) where EventType : UnityEvent
    {
        GetEvent<EventType>().RemoveListener(listener);
    }

    public static void Trigger<EventType>() where EventType : UnityEvent
    {
        GetEvent<EventType>().Invoke();
    }

    public static void Trigger<EventType, FirstParam>(FirstParam firstParam) where EventType : UnityEvent
    {
        GetEvent<EventType>().Invoke(firstParam);
    }
}

Другие сценарии могут подписываться на события / отписываться от них и инициировать их. Теперь возникают две проблемы, которые принадлежат друг другу:

  • Я не могу сохранить свои универсальные UnityEvent в словаре, потому что он может содержать только неуниверсальные

Лучший перегруженный метод Add 'Dictionary.Add (Type, UnityEvent)' для инициализатора коллекции имеет недопустимые аргументы (CS1950) [Assembly-CSharp] Аргумент 2: невозможно преобразовать из 'LevelSceneLoadedGameEvent' в 'UnityEngine.Events. UnityEvent '(CS1503) [Assembly-CSharp]

  • Мой Trigger метод с одним аргументом завершается с ошибкой Invoke, поскольку GetEvent возвращает неуниверсальный UnityEvent

Никакая перегрузка для метода 'Invoke' требует 1 аргумента (CS1501) [Assembly-CSharp]

Как я могу исправить свой EventManager , чтобы иметь делос неуниверсальным и универсальным UnityEvents?

Ответы [ 2 ]

3 голосов
/ 06 октября 2019

UnityEvent имеет несколько общих перегрузок, которые вы можете использовать для добавления параметров (таких как строки, целые числа и т. Д.)

В принципе любой тип данных, который Unity будет сериализовать, будет отображаться в инспекторе. Поэтому вам, в основном, нужно использовать UnityEvent<string>, например, если вы хотите вызвать событие со строкой.

Здесь - это пример использования единственного параметра UnityEvent.

0 голосов
/ 06 октября 2019

Я исправил это, приведя UnityEvent, который я получаю из словаря, к универсальному типу, который я хочу, и при добавлении события в словарь я приводил его к UnityEvent. Далее я должен использовать UnityEventBase для словаря, так как это базовый класс для событий.

Фиксированный код:

public static class GameEventManager
{
    private static Dictionary<Type, UnityEventBase> events = new Dictionary<Type, UnityEventBase>()
    {
        {
            typeof(LevelSceneLoadedGameEvent),
            new LevelSceneLoadedGameEvent()
        }
    };

    private static EventType GetEvent<EventType>() where EventType : UnityEventBase
    {
        UnityEventBase unityEvent = events[typeof(EventType)];
        return (EventType)unityEvent;
    }

    public static void SubscribeTo<EventType>(UnityAction listener) where EventType : UnityEvent
    {
        GetEvent<EventType>().AddListener(listener);
    }

    public static void UnsubscribeFrom<EventType>(UnityAction listener) where EventType : UnityEvent
    {
        GetEvent<EventType>().RemoveListener(listener);
    }

    public static void SubscribeTo<EventType, FirstParam>(UnityAction<FirstParam> listener) where EventType : UnityEvent<FirstParam>
    {
        GetEvent<EventType>().AddListener(listener);
    }

    public static void UnsubscribeFrom<EventType, FirstParam>(UnityAction<FirstParam> listener) where EventType : UnityEvent<FirstParam>
    {
        GetEvent<EventType>().RemoveListener(listener);
    }

    public static void Trigger<EventType>() where EventType : UnityEvent
    {
        GetEvent<EventType>().Invoke();
    }

    public static void Trigger<EventType, FirstParam>(FirstParam firstParam) where EventType : UnityEvent<FirstParam>
    {
        GetEvent<EventType>().Invoke(firstParam);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...