- Home /
Can I use an interface to subscribe a script to a multicast delegate? Or, what would be a good alternative?
One of the many "golden rules" of programming is that if you're copying code, you're probably doing something wrong.
I have a singleton (gasp) that manages game ticks, and on every game tick it invokes the OnGameTick
delegate.
I have many scripts that do their own things when OnGameTick
is invoked, but they all do it through the DoGameTick()
method. So, right now, I have all of these scripts inherit from abstract class TickUpdatingMonoBehavior
, which is where the OnEnable()
and OnDisable()
methods subscribe and unsubscribe abstract void DoGameTick()
to the OnGameTick
delegate. That way, I don't need to type it out for every script, and as a bonus the compiler tells me when I haven't implemented DoGameTick()
.
However, this means that I cannot have these methods inherit from anything else (except other children). I want to use an interface called like IUpdateOnTick
or something, but interfaces don't support default implementation and can't even call OnEnable()
and OnDisable()
. The interface could still define DoGameTick()
but that doesn't accomplish much on its own.
Answer by Hellium · Mar 24 at 07:04 PM
When inheritance causes problems, composition often helps.
public interface ITickable
{
void DoGameTick();
}
// Will automatically add TickExecutor component when this component is added
[RequireComponent(typeof(TickExecutor))]
public class MyMonoBehaviour : MyBaseClass, ITickable
{
public void DoGameTick()
{
Debug.Log("Tick");
}
}
public class TickExecutor : MonoBehaviour
{
private ITickable tickable;
void OnEnable()
{
tickable = GetComponent<ITickable>();
if(tickable != null)
GameManager.OnGameTick += tickable.DoGameTick;
}
void OnDisable()
{
if(tickable != null)
GameManager.OnGameTick += tickable.DoGameTick;
}
}
Aggh but that makes DoGameTick public. Unity is really trying to force me to relax my opinions on visibility
It's not Unity which causes the function to be public, it's the use of the interface.
Right, I'm just saying in my limited time with Unity I've found that it usually requires design patters that aren't overly concerned with proper encapsulation.
For example, in one of my previous questions I was trying to add a component to an object at runtime and I wanted that component to have private fields but since you can't add components with a constructor the fields needed public setters, which otherwise wouldn't have been necessary.
In the end it doesn't really matter and I'm being obsessive.
Answer by PiterQ70 · Mar 26 at 07:49 PM
IDK exactly what you want to achieve but there is couple tricks that can be useful :)
public interface ITickable
{
protected internal void Bla() { Debug.Log(""); }
internal void Init() { Debug.Log("Some initialization things?"); }
}
public class A : ITickable
{
public A()
{
((ITickable)this).Init();
}
}
public class B : MonoBehaviour
{
ITickable tickable;
A Aclass;
private void Awake()
{
((ITickable)Aclass).Init();
tickable.Init();
}
void Call()
{
((ITickable)Aclass).Bla();
tickable.Bla();
}
}
public class C: MonoBehaviour, ITickable
{
private void Awake()
{
((ITickable)this).Init();
A AclassInit = new();
}
}
or maybe events?
public class TickUpdater : MonoBehaviour
{
public static event System.Action OnTick;
public static event System.Action<String> OnTickWithParams;
private void Start()
{
OnTick();
OnTickWithParams("some text");
}
}
public interface ITickReceiver
{
public void RegisterEvent() { InternalRegisterEvent(); }
private void InternalRegisterEvent() { TickUpdater.OnTick += DoTickFromInterface; }
void DoTickFromInterface();
}
public class TickReceiver : MonoBehaviour, ITickReceiver
{
private void Awake()
{
TickUpdater.OnTick += DoTick;
TickUpdater.OnTickWithParams += DoTickWithParams;
(this as ITickReceiver).RegisterEvent();
}
private void DoTick() { }
public void DoTickFromInterface() { }
private void DoTickWithParams(string obj) { }
}
Unity does not support default interface members
And the current solution already uses events. The original author wants to avoid the inheritance from a class handling the subscription and unsubscription to the event.
What Unity version are you using? Unity support default interface members form 2021.2b6 Forum thread
My bad, I got fooled by Google which got me the 2020.3 version of the documentation.
I can't blame it as it's the LTS version.
Answer by ArmanDoesStuff · Mar 24 at 06:49 PM
Can't you just make abstract void DoGameTick() virtual, and then override it as needed?
An abstract method is a virtual method, just with no default implementation so a derived class is required to override the method.
Your answer
![](https://koobas.hobune.stream/wayback/20220613054557im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Need to inherit from EventArgs AND ScriptableObject 1 Answer
Interaction script 2 Answers
Calling a method using delegate makes my object null 0 Answers
Implementing Unity's Callback System 1 Answer
How to unsubscribe from InputSystem event properly 0 Answers