2
\$\begingroup\$

I was inspired by a great talk at Unite by Ryan Hipple.

https://youtu.be/raQ3iHhE_Kk?t=28m

His examples didn’t cover passing arguments with UnityEvents

Do I need to extend UnityEvent, GameEvent and GameEventListener from a generic base class for this to work properly?

If so do I need to make a new set of classes for each Type and combination of Types that I want to pass?

Game Event Scriptable Object

[CreateAssetMenu]
    public class GameEvent : ScriptableObject
    {
        /// <summary>
        /// The list of listeners that this event will notify if it is raised.
        /// </summary>
        private readonly List<GameEventListener> eventListeners = 
            new List<GameEventListener>();

        public void Raise()
        {
            for(int i = eventListeners.Count -1; i >= 0; i--)
                eventListeners[i].OnEventRaised();
        }

        public void RegisterListener(GameEventListener listener)
        {
            if (!eventListeners.Contains(listener))
                eventListeners.Add(listener);
        }

        public void UnregisterListener(GameEventListener listener)
        {
            if (eventListeners.Contains(listener))
                eventListeners.Remove(listener);
        }
    }

Listener Class

public class GameEventListener : MonoBehaviour
    {
        [Tooltip("Event to register with.")]
        public GameEvent Event;

        [Tooltip("Response to invoke when Event is raised.")]
        public UnityEvent Response;

        private void OnEnable()
        {
            Event.RegisterListener(this);
        }

        private void OnDisable()
        {
            Event.UnregisterListener(this);
        }

        public void OnEventRaised()
        {
            Response.Invoke();
        }
    }
\$\endgroup\$
2
\$\begingroup\$

Yes, you will have to create a sub-class of the UnityEvent class as follow:

[System.Serializable]
public class GameObjectEvent : UnityEngine.Events.UnityEvent<GameObject> {} // Leave it empty

And then:

public class GameEventListener : MonoBehaviour
{
    [Tooltip("Event to register with.")]
    public GameEvent Event;

    [Tooltip("Response to invoke when Event is raised.")]
    public GameObjectEvent Response;

    private void OnEnable()
    {
        Event.RegisterListener(this);
    }

    private void OnDisable()
    {
        Event.UnregisterListener(this);
    }

    public void OnEventRaised()
    {
        Response.Invoke( gameObject );
    }
}

I have never found an alternative to create a new class for every type, except using System.Action<your_type>, but you won't be able to use the Inspector anymore to call the function you want (unless you have a plugin to serialize the System.Action)

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Can you pass in custom classes or only game objects and primitives ? \$\endgroup\$ – Pyreal Apr 19 '18 at 21:18
  • \$\begingroup\$ You can pass the type you want :) \$\endgroup\$ – Hellium Apr 20 '18 at 7:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.