在Entity Component Systems中,实体与组件中的数据保持关系,然后每个组件都可以由多个系统来操作。每个系统都可以依赖于许多组件。
当前,我正在基类中实现系统,并进行了大量繁重的工作来查找并将组件耦合到同一实体。许多操作都是使用泛型完成的,并且效果很好。
public abstract class System<T1>: System
where T1: Component
{
public override void Update( long delta )
{
ComponentStorage<Component> componentStorage1 = GetComponentStorageByType<T1>( );
List<Entity> entities = GetEntities( );
if ( componentStorage1 == null )
return;
entities.ForEach( e =>
{
int index = entities.IndexOf( e );
if ( componentStorage1[ index ] == null )
return;
Update( (T1) componentStorage1[ index ], delta );
} );
}
protected abstract void Update( T1 component1, long delta );
}
继承的类重写了称为Update的方法,我将实例化的组件从存储传递给update方法。
class TestSystem1: System<TestComponent1>
{
protected override void Update( TestComponent1 component1, long delta )
{
Console.WriteLine( $"{component1.Count++}" );
}
}
这仅适用于只有一个组件的系统。如果系统具有多个组件,那么我将不得不为多个组件添加另一个通用Tn,这意味着最多可以实现无限数量的类。
我研究了数量可变的通用参数,C++11 has it但 C# does not。
我也许可以使反射适合魔术,但是直到我用尽所有其他选项之前,我宁愿不这样做。
有没有可以满足我需求的设计?我希望继承的类保持最完整 -调用覆盖的,受保护的Update方法(或类似方法),并将已转换的组件交给它。
答案 0 :(得分:1)
一些可能的选项是:
System<>
基类,并支持例如1至16个参数。这是一个编译时解决方案。System<T>
仅接受一个参数,但是如果T
本身不是组件,请将其视为组合。 IMO,它的实现和使用都更加简单。例如: class ComponentsRequired
{
Component1 First { get; set; }
Component2 Second { get; set; }
}
class TestSystem : System<ComponentsRequired>
{
protected override void Update( ComponentsRequired components, long delta )
{
Console.WriteLine( $"{components.First}" );
Console.WriteLine( $"{components.Second}" );
}
}
反射可用于一次获取ComponentsRequired
中的属性类型,然后将其缓存以加快下次速度。