在基于事件的架构中通过UnityEvent传递数据

时间:2019-10-06 06:50:21

标签: c# unity3d

我来自这篇文章

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 个答案:

答案 0 :(得分:3)

UnityEvent有几个泛型重载,可用于添加参数(例如字符串,整数等)

基本上,Unity会序列化的任何数据类型都会显示在检查器中。 因此,如果您希望使用字符串引发事件,则基本上需要使用UnityEvent<string>

Here是使用单个参数UnityEvent的示例。

答案 1 :(得分:0)

我通过将从字典获得的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);
    }
}