I'm making a game and I'm using a lot of events to make one class communicate with others, but its tiresome to handle the subscription and the unsubscription on the OnEnable and OnDisable methods everytime that a new class will listen to a certain event. So I thought about making abstract classes for specific events and then, the class that wants to listen to the event will only have to inherit from the abstract class, to save time from setting up the method, OnEnable and OnDisable again.
The abstract class will be like this:
Lets say we have an event called OnGameStart. I'd make an abstract class just to listen to this event.
public abstact class OnGameStartListener : Monobehaviour
{
private void OnEnable() => Controller.OnGameStart += OnGameStart;
private void OnDisable() => Controller.OnGameStart -= OnGameStart;
public abstract void OnGameStart();
}
Then, a class that wants to listen to this event would simply enherit from the abstract class and override the abstract method.
My question is: Is there a better way to do this? Or is this too much expensive? Because if a class Inherits from more than one abstract class to listen to events, we'd have more OnEnable and OnDisable methods being called.
Thanks for the time reading and answering ;)
I havent tried this yet, because Im not sure if its worth it. Not sure how I'd analyze the efficiency too.
As already mentioned by TimChang in the comments: There is no way in c# that you
Inherit from more than one abstract class
in the first place.
If you go for an abstract class
you should make OnEnable
and OnDisable
rather protected virtual void
and if you then override
it in a child class make sure to also call base.OnEnable();
accordingly. Otherwise there might be unexpected behavior as you don't know which of the OnEnable
will be called by the engine.
Also OnGameStart
should then rather be protected abstract void
as there is no intend to have it called from the outside.
But if you say you have different events you should rather go for interface
s.
Assume something like e.g.
public interface IGameStartListener
{
void OnGameStart();
}
public interface IGameEndListener
{
void OnGameEnd();
}
And then you can have a class like e.g.
public class Something : MonoBehaviour, IGameStartListener, IGameEndListener
{
void OnEnable()
{
Controller.AddListener(this);
}
void OnDisable()
{
Controller.RemoveListener(this);
}
public void OnGameStart() { }
public void OnGameEnd() { }
}
where your Controller
can simply have multiple events and do something like e.g.
static event Action OnGameStart;
static event Action OnGameEnd;
...
public static void AddListener(object listener)
{
if(listener is IGameStartListener gameStartListener)
{
OnGameStart += gameStartListener.OnGameStart;
}
if(listener is IGameEndListener gameEndListener)
{
OnGameEnd += gameStartListener.OnGameEnd;
}
...
}
public static void RemoveListener(object listener)
{
if(listener is IGameStartListener gameStartListener)
{
OnGameStart -= gameStartListener.OnGameStart;
}
if(listener is IGameEndListener gameEndListener)
{
OnGameEnd -= gameStartListener.OnGameEnd;
}
...
}
For sure as you can see every implementer of the interfaces still has to ensure itself that it is properly registered and unregistered as a listener.
If you want to avoid this of course you still could simply have a base class that implements them all as virtual
which means the behavior can be overwritten by any inheritor.
public abstract class MonoBehaviourGameEvents : MonoBehaviour, IGameStartListener, IGameEndListener, ...
{
virtual void OnEnable()
{
Controller.AddListener(this);
}
virtual void OnDisable()
{
Controller.RemoveListener(this);
}
public virtual void OnGameStart() { }
public virtual void OnGameEnd() { }
...
}
This would be more of a convinience implementation if you don't want to handle the registration yourself - but still using interfaces so you can be flexible if you want / need to