【发布时间】:2012-09-11 21:53:21
【问题描述】:
我想我会在我的代码中使用一个案例研究作为我的意思的例子。
现在,我正在为我的基于组件的游戏系统开发一个行为/动作系统。 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 等)之外想要什么。 /p>
是否有一种更简洁的方法来处理这个问题,这将允许我公开在子类中定义的这些属性,而不必将检索到的 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
}
}
现在我在想那是唯一的方法,但我想我会看看木制品中是否隐藏着我不知道的图案,或者是否有人可以提出更好的建议实现这一点的方法开始。
谢谢!
【问题讨论】:
-
我的另一个想法是在内部使用另一个对象,例如 IActionComponentExecutor,它会决定何时调用 Action.Execute(),但我认为这让我回到了一个圆-a-回合时尚 - 然后外部对象将不得不追踪 IActionComponentTimedExecutor(哦~我们现在开始'企业-y!)以更改 IdleTime。
-
出于兴趣 - actionComponent.IdleTime 的状态是否存储在某种通用包中?如果是这样,您可以在基本接口上使用
Apply(BagData bag)和Store(BagData bag)方法。也就是说,您可能还需要考虑一些元数据类型系统,您可以使用它来查询需要知道派生类型的属性。TypeDescriptor是一个现成的起点,供属性网格等使用。 -
不,目前不是。我也不完全熟悉这个概念 - 您是否可以提供参考?
-
好吧,真的,我想它就像序列化一样。但是,如果您希望能够编写这样的代码,因为它知道派生接口,所以它可能不适合“知道”存在可以设置的值。
-
好的,有道理。不过,我认为对于这种情况,它可能有点太一般。其他代码将知道派生接口,我只需要一个很好的方法来获得该访问权限。
标签: c# inheritance interface