listunity-game-engineeventsnullscriptable-object

Scriptable Object Events Cannot Register Listeners (records type mismatch) in Unity


I'm trying to follow a tutorial for handling events with scriptable objects which I found on Youtube, which is located here: https://www.youtube.com/watch?v=7_dyDmF0Ktw

As a result, I've got two scripts which as far as I can tell, match the scripts that he is using, as follows: Script 1:

[CreateAssetMenu(menuName = "GameEvent")]
public class GameEvent : ScriptableObject
{
    private List<GameEventListener> listeners = new List<GameEventListener>();

    public void Raise()
    {
        Raise(null, null);
    }
    
    public void Raise(Component sender, object data)
    {
        for (int i = 0; i < listeners.Count; i++)
        {
            listeners[i].OnEventRaised(sender, data);
        }
    }

    public void RegisterListener(GameEventListener listener)
    {
        Debug.Log(listener.GetType());
        if (!listeners.Contains(listener))
        {
            listeners.Add(listener);
        }
        Debug.Log(listeners[0]);
    }

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

Script 2:

[Serializable] public class CustomUnityEvent : UnityEvent<Component, object> { }

public class GameEventListener : MonoBehaviour
{
    public GameEvent gameEvent;
        
    public CustomUnityEvent response;

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

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

    public void OnEventRaised(Component sender, object data)
    {
        response.Invoke(sender, data);
    }
}

I've added the scripts to the appropriate objects, and created the event just as it was in the video, and set all the required references. The problem arises during the RegisterListener method. As you can see in Script 1, I've included 2 debugs printouts. In the first one, it gets the type of the listener, and this correctly comes up as "GameEventListener", however after the registering step, the second debug records that what has been added to the list is a null reference.

The expected result is that it would be adding a GameEventListener. I'm using Unity 2021.3.25. Am I missing a step in my code somewhere? Why is it adding a null when the type is reporting as GameEventListener just before this?

I've tried setting the list to public as well as private which I don't think would have an effect, and the results are the same. I'm still expecting it to add a GameEventListener, because that is the type that is being shown in the Debug, but it's adding a null, which results in a type mismatch in the list.


Solution

  • This does not make any sense. If the collection does NOT contain item you remove it?

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

    Also Remove returns true if succeded and false if not. So you can check that if you really want to make sure something was removed

    public void UnregisterListener(GameEventListener listener)
    {
        if (listeners.Remove(listener))
        {
            //On listener removed can be added here later
        }
    }