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.
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;
}
}
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) { }
}
Can’t you just make abstract void DoGameTick() virtual, and then override it as needed?