我想我将在我的代码中使用一个案例研究作为我的意思的例子。
现在,我正在为基于组件的游戏系统开发行为/动作系统。GameObjects 可以有一个 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
}
}
现在我在想那是唯一的方法,但我想我会看看木制品中是否隐藏着一种我不知道的图案,或者是否有人可以提出一种更好的方法来完成这一点。
谢谢!