我相信我已经完成了使用XNA的C#组件化游戏引擎中的最后一个大的逻辑跳跃。我已经定义了Entity类和抽象组件。我的问题出现在EntityFactory中。
当我想要创建一个新实体时,我将EntityType枚举传递给工厂中的静态方法,并通过switch/case语句找到需要组合的组件。问题是,我正在尝试创建一种方法,使得组件可以共享与同一实体中的其他组件相同的字段,而不必访问所有内容。例如,如果两个组件具有表示位置的Vector2字段,则它们应该都指向同一个Vector2。
我可以通过在实体工厂中初始化所有字段并要求将其传递到组件的构造函数中(并使用原始类型的ref),来实现这一点。但是,这将非常难以维护,因为每次我扩展或更改组件时,我都必须在使用该组件的每个地方重新编写工厂中的代码。我真的想避免这种解决方案,但如果我找不到更好的方法,我将忍受它。
我目前的解决方案是创建一个名为Attribute的包装器类。它包含两个字段:
private AttributeType type;
private Object data;
属性类型是一个枚举,表示属性的目的。因此,在枚举中有位置、旋转、纹理等条目。
EntityFactory创建一个空属性列表,并将其传递给每个组件构造函数。setField方法将由组件的构造函数调用,而不是初始化字段。这是Attribute类和setField方法:
public class Attribute
{
private AttributeType type;
private Object data;
public AttributeType Type
{
get { return this.type; }
}
public Object Data
{
get { return this.data; }
}
public Attribute(AttributeType type, Object data)
{
this.type = type;
this.data = data;
}
public static void setField<T>(List<Attribute> attributeList, AttributeType type, out T field, T defaultValue)
{
bool attributeFound = false;
field = defaultValue;
foreach (Attribute attribute in attributeList)
{
if (attribute.Type == type)
{
field = (T)attribute.Data;
attributeFound = true;
break;
}
}
if (!attributeFound)
{
attributeList.Add(new Attribute(type, field));
}
}
}
我的问题是当属性包含原始数据类型的数据时。我考虑在Attribute类中编写一个方法。
public void getData<T>(out T field) { field = this.data; }
然而,我似乎无法使用ref将数据传递给Attribute构造函数。我无法使Attribute成为通用类型,因为它不能进入列表中。我只是想知道是否有一种方法来处理值类型和引用类型的数据,或者在整个过程中我是否犯了逻辑错误。
SimpleRenderer
与IPositionComponent
(在代码和组合对象定义中)耦合起来。它避免了糟糕的耦合方式——例如SimpleRenderer
可能依赖于特定的位置提供者,如StaticPosition
和PhysicsPosition
。 - Andrew RussellVector2
)的引用。但是这是不可能的。值类型总是被复制的,并且当它们被装箱成引用类型时,它们是不可变的。唯一的方法是拥有一个对可变值类型的“引用”,就是它是一个class
的成员(就像你的Attribute
,或者类似于我的IPositionComponent
),并且你总是通过那个类访问它。(ref
参数则完全不同。) - Andrew Russell