I believe that as an example of what I mean, I will use the example from my code.
I am currently working on a behavior / action system for my component-based game system. GameObjects can have an IBehaviorComponent and an IActionComponent attached to it, which, showing only the relevant data, exposes the following:
public interface IBehaviorComponent : IBaseComponent { IBehavior Behavior { get; } } public interface IActionComponent : IBaseComponent { IAction Action { get; } void ExecuteAction(IGameObject target = null); }
Now everything is fine (at least for me!). But the problem starts with brew when I look at IActionComponent implementations.
For example, a simple implementation of IActionComponent:
public class SimpleActionComponent : IActionComponent { public IAction Action { get; protected set; } public void ExecuteAction(IGameObject target = null) { Action.Execute(target); } public void Update(float deltaTime) { }
But let's say I want to introduce a more complex implementation of IActionComponent, which allows you to perform scheduled actions:
public class TimedActionComponent : IActionComponent { public IAction Action { get; protected set; } public float IdleTime { get; set; } public float IdleTimeRemaining { get; protected set; } public void ExecuteAction(IGameObject target = null) { IdleTimeRemaining = IdleTime; } public void Update(float deltaTime) { if (IdleTimeRemaining > 0f) { IdleTimeRemaining -= deltaTime; } else { Action.Execute(target); } } }
And now, let's say, I want to expose IdleTime so that it can be changed by external influences. My thoughts at first were to create a new interface:
public interface ITimedActionComponent : IActionComponent { float IdleTime { get; set; } float IdleTimeRemaining { get; set; } }
However, the problem is that my component system stores everything at the same level from IBaseComponent. Thus, the action component for a GameObject is retrieved as an IActionComponent, not like ITimedActionComponent, or IRandomizedActionComponent, or even ICrashTheProgramActionComponent. I hope the reasons for this are obvious, since I want something to be able to request a GameObject for one of its components, not knowing exactly what it wants, besides the main component type (IActionComponent, IRenderableComponent, IPhysicsComponent, etc.)
Is there a cleaner way to handle this that allows me to expose these properties defined in child classes without having to pass all that was needed to the selected IActionComponent in the type of interest to it? Or is it just the only / best way to achieve this. Sort of:
public void IWantYouToAttackSuperSlow(IGameObject target) {
Right now, I think the โOnly Wayโ, but I thought I'd see if there was a pattern lurking in a tree that I didn't know about, or if someone could suggest a much better way to accomplish this, to start with.
Thanks!