0
\$\begingroup\$

My question is more C# than Unity, but it relies on a Unity specific delegate, also, sorry if the title is not that clear to what I'm trying to do. I have implemented a simple event manager which uses a dictionary of <EventName,UnityEvent<object>>.

It works great for what I want, but as it encapsulates a UnityEvent<object> it converts my parameters to object instead of their concrete classes.

I've tried doing the following to be able to register the delegate for the events using the concrete type parameter.

Created an interface and BaseEventData class:

    public interface IEventData {}

    public abstract class BaseEventData : IEventData {}

Created a custom UnityEvent for this type parameter

    [Serializable]
    public class CustomDataEvent<T> : UnityEvent<T> where T : IEventData {}

Then I have my dictionary:

protected internal Dictionary<EventName, CustomDataEvent<IEventData>> CustomEventDictionary;

What I want to be able to do is:

EventManager.StartListening<DummyEventData>(EventName.DummyEvent, DummyEventData data => Method(data));

So that my method/delegate can use DummyEventData as the parameter type instead of IEventData/object and then need to cast it to DummyEventData.

What I've tried doing on my register method:

public static void StartListening<T>(EventName eventName, UnityAction<T> listener) where T : IEventData
        {
            if (Instance.CustomEventDictionary.TryGetValue(eventName, out var thisEvent))
            {
                thisEvent.AddListener(listener);
            }
            else
            {
                thisEvent = new CustomDataEvent<IEventData>();
                thisEvent.AddListener(listener);
                Instance.CustomEventDictionary.Add(eventName, thisEvent);
            }
        }

However, this is not possible, the compiler says that UnityAction<T> is not assignable to UnityAction<IEventData>, I've read about covariance and contravariance which seems to be the issue here, but as this involves UnityAction I could not implement the solution I found on this question, is there a way, if any, to achieve what I'm trying to?

\$\endgroup\$
3
  • \$\begingroup\$ You may be interested in Centralized event system using dictionary. \$\endgroup\$ Commented Jan 2, 2024 at 20:33
  • \$\begingroup\$ @DMGregory So basically instead of a event manager, I would only have the events themselves to register the listener and trigger them? I'm assuming this approach would be better than having the events populate a dictionary on the memory, right? \$\endgroup\$ Commented Jan 3, 2024 at 15:34
  • \$\begingroup\$ They're stored more densely this way, without the holes you get in a hashmap, and without the extra hashing step. As I mention in a comment below that answer, using a struct type for the data payload would help avoid allocations when firing events. \$\endgroup\$ Commented Jan 3, 2024 at 17:14

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.