具有结构的 ECS 中的组件实现
Component Implementation in a ECS with structs
目标:
我正在尝试实现一个实体组件系统,但我被组件实现困住了。我打算有一个通用组件类型,其中包含每个组件的静态位,例如Position 类型的组件具有 Bit=0,Sprite 类型的组件具有 Bit=1,等等。一个组件应该只包含它所拥有的值,因此我从结构开始。以下是我对此的尝试(不是工作代码):
struct Position : Component<Position> //this does not work in c#
{
public int x, y;
}
internal struct ComponentBit
{
public static int bitCounter = 0;
};
public struct Component<T>
{
public static readonly int bit;
static Component()
{
bit = ComponentBit.bitCounter++;
}
public int GetBit()
{
return bit;
}
}
在那之后我发现结构无法继承,所以我尝试将结构更改为 类 有效。
问题:
是否有任何方法可以像在 C++(模板)中那样使用结构来实现这些功能?出于 implementation/performance 原因,我想将它们保留为值类型而不是引用类型。
编辑1:
我想要的预期用途是:
Position pos = new Position(x, y);
int bit1 = pos.GetBit(); // or
int bit2 = Position.bit; // both should be possible
我的建议是不要尝试使用继承。
任何结构都是可能的有效组件,例如:
struct Position
{
public int X, Y;
public Position(int x, int y)
{
X = x;
Y = y;
}
}
现在,您仍然可以使用 Component<T>
作为 int 字典 (Dictionary<Type, int>
) 的类型。虽然,我将以最少的更改来完成这项工作:
internal static class ComponentBit
{
public static int bitCounter = 0;
};
public static class Component<T>
{
public static readonly int bit; // This is static, it has a value per type T
static Component()
{
bit = ComponentBit.bitCounter++;
}
public static int GetBit()
{
// This method only accesses static members, it can be static
// Thus, no instance of T is needed
return bit;
}
}
你会像这样使用它:
Position pos = new Position(x, y);
int bit1 = Component<Position>.GetBit();
int bit2 = Component<Position>.bit;
不知道你为什么要用两种方法来做这件事,但你去吧。
好吧,现在我将自由地做更大的改变......考虑到这一点,如果你想要类型推断,你可以这样做:
public static class Component
{
internal static int bitCounter = 0;
public static int GetBit<T>()
where T : struct // We only accept structs here
{
return Component<T>.bit;
}
public static int GetBit<T>(this ref T value)
where T : struct // We only accept structs here
{
// This is an extension method.
// It will appear as a method on any valid T (which is all structs)
// The type T will be infered from the instance.
// Passing the struct as a reference to avoid a copy
_ = value; // discard value
return GetBit<T>();
}
};
internal static class Component<T>
where T : struct // We only accept structs here
{
internal static readonly int bit;
static Component()
{
bit = Component.bitCounter++;
}
}
用法:
var pos = new Position(x, y);
var bit1 = Component.GetBit<Position>();
var bit2 = pos.GetBit();
是的,以上代码编译运行。在 SharpLab.
中查看
注意:我会考虑在 Component
中嵌套 Component<T>
。
目标:
我正在尝试实现一个实体组件系统,但我被组件实现困住了。我打算有一个通用组件类型,其中包含每个组件的静态位,例如Position 类型的组件具有 Bit=0,Sprite 类型的组件具有 Bit=1,等等。一个组件应该只包含它所拥有的值,因此我从结构开始。以下是我对此的尝试(不是工作代码):
struct Position : Component<Position> //this does not work in c#
{
public int x, y;
}
internal struct ComponentBit
{
public static int bitCounter = 0;
};
public struct Component<T>
{
public static readonly int bit;
static Component()
{
bit = ComponentBit.bitCounter++;
}
public int GetBit()
{
return bit;
}
}
在那之后我发现结构无法继承,所以我尝试将结构更改为 类 有效。
问题:
是否有任何方法可以像在 C++(模板)中那样使用结构来实现这些功能?出于 implementation/performance 原因,我想将它们保留为值类型而不是引用类型。
编辑1:
我想要的预期用途是:
Position pos = new Position(x, y);
int bit1 = pos.GetBit(); // or
int bit2 = Position.bit; // both should be possible
我的建议是不要尝试使用继承。
任何结构都是可能的有效组件,例如:
struct Position
{
public int X, Y;
public Position(int x, int y)
{
X = x;
Y = y;
}
}
现在,您仍然可以使用 Component<T>
作为 int 字典 (Dictionary<Type, int>
) 的类型。虽然,我将以最少的更改来完成这项工作:
internal static class ComponentBit
{
public static int bitCounter = 0;
};
public static class Component<T>
{
public static readonly int bit; // This is static, it has a value per type T
static Component()
{
bit = ComponentBit.bitCounter++;
}
public static int GetBit()
{
// This method only accesses static members, it can be static
// Thus, no instance of T is needed
return bit;
}
}
你会像这样使用它:
Position pos = new Position(x, y);
int bit1 = Component<Position>.GetBit();
int bit2 = Component<Position>.bit;
不知道你为什么要用两种方法来做这件事,但你去吧。
好吧,现在我将自由地做更大的改变......考虑到这一点,如果你想要类型推断,你可以这样做:
public static class Component
{
internal static int bitCounter = 0;
public static int GetBit<T>()
where T : struct // We only accept structs here
{
return Component<T>.bit;
}
public static int GetBit<T>(this ref T value)
where T : struct // We only accept structs here
{
// This is an extension method.
// It will appear as a method on any valid T (which is all structs)
// The type T will be infered from the instance.
// Passing the struct as a reference to avoid a copy
_ = value; // discard value
return GetBit<T>();
}
};
internal static class Component<T>
where T : struct // We only accept structs here
{
internal static readonly int bit;
static Component()
{
bit = Component.bitCounter++;
}
}
用法:
var pos = new Position(x, y);
var bit1 = Component.GetBit<Position>();
var bit2 = pos.GetBit();
是的,以上代码编译运行。在 SharpLab.
中查看注意:我会考虑在 Component
中嵌套 Component<T>
。