我打算举一个我的代码中的案例来说明我的意思。
现在,我正在为我的组件化游戏系统开发一个行为/动作系统。游戏对象可以附加IBehaviorComponent和IActionComponent,它们只显示相关细节,如下所示:
public interface IBehaviorComponent : IBaseComponent
{
IBehavior Behavior { get; }
}
public interface IActionComponent : IBaseComponent
{
IAction Action { get; }
void ExecuteAction(IGameObject target = null);
}
现在,到目前为止一切都很好(至少对我来说是这样的!)。但是,当我看到IActionComponent的实现时,问题开始酝酿。
例如,一个简单的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) { } //from IBaseComponent
}
但是,假设我想引入一个更复杂的IActionComponent实现,允许在定时计划上执行操作:
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);
}
}
}
现在,假设我想要公开IdleTime,以便外部因素可以进行更改。一开始我的想法是创建一个新的接口:
public interface ITimedActionComponent : IActionComponent
{
float IdleTime { get; set; }
float IdleTimeRemaining { get; set; }
}
然而,在我的组件系统中,所有东西都存储在IBaseComponent的一级上。因此,GameObject的操作组件被检索为IActionComponent,而不是ITimedActionComponent、IRandomizedActionComponent甚至是ICrashTheProgramActionComponent。我希望这样做的原因很明显,我希望任何东西都可以查询GameObject的一个组件,而无需知道它需要什么除了基本类型的组件(IActionComponent、IRenderableComponent、IPhysicsComponent等)。
有没有更简单的处理方式,可以让我暴露子类中定义的这些属性,而不必让每个东西都将检索到的IActionComponent转换为它感兴趣的类型呢?或者说这只是完成这项任务的唯一/最佳方式?例如:
public void IWantYouToAttackSuperSlow(IGameObject target)
{
//Let's get the action component for the gameobject and test if it's an ITimedActionComponent...
ITimedActionComponent actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent;
if (actionComponent != null) //We're okay!
{
actionComponent.IdleTime = int.MaxValue; //Mwhaha
}
}
我现在认为这是唯一的方法,但我想看看是否有隐藏在木工中我不知道的模式,或者是否有人能建议更好的方法来实现这个目标。
谢谢!