C# 具有结构的ECS中的组件实现

C# 具有结构的ECS中的组件实现,c#,generics,static-members,entity-component-system,C#,Generics,Static Members,Entity Component System,目标: 我正在尝试实现一个实体组件系统,我一直在坚持我的组件实现。我希望有一个通用组件类型,其中包含每个组件的静态位,例如,Position类型的组件的位=0,Sprite类型的组件的位=1,等等。组件应该只包含它所持有的值,因此我从结构开始。以下是我对此(非工作代码)的尝试: 我的建议是不要尝试使用继承 任何结构都可能是有效组件,例如: struct Position { public int X, Y; public Position(int x, int y) {

目标:

我正在尝试实现一个实体组件系统,我一直在坚持我的组件实现。我希望有一个通用组件类型,其中包含每个组件的静态位,例如,Position类型的组件的位=0,Sprite类型的组件的位=1,等等。组件应该只包含它所持有的值,因此我从结构开始。以下是我对此(非工作代码)的尝试:


我的建议是不要尝试使用继承

任何结构都可能是有效组件,例如:

struct Position
{
    public int X, Y;

    public Position(int x, int y)
    {
        X = x;
        Y = y;
    }
}
现在,您仍然可以使用
组件
作为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;
    }
}
内部静态类ComponentBit
{
公共静态int位计数器=0;
};
公共静态类组件
{
public static readonly int bit;//这是静态的,每个类型T都有一个值
静态组件()
{
位=组件位。位计数器++;
}
公共静态int GetBit()
{
//此方法仅访问静态成员,可以是静态的
//因此,不需要T的实例
返回位;
}
}
你可以这样使用它:

Position pos = new Position(x, y);
int bit1 = Component<Position>.GetBit();
int bit2 = Component<Position>.bit;
位置pos=新位置(x,y);
int bit1=Component.GetBit();
int bit2=Component.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++;
    }
}
公共静态类组件
{
内部静态整数位计数器=0;
公共静态int GetBit()
其中T:struct//我们这里只接受struct
{
返回组件.bit;
}
公共静态int GetBit(此参考T值)
其中T:struct//我们这里只接受struct
{
//这是一种扩展方法。
//它将在任何有效的T(都是结构)上显示为方法
//类型T将从实例中推断出来。
//将结构作为引用传递以避免复制
_=值;//放弃值
返回GetBit();
}
};
内部静态类组件
其中T:struct//我们这里只接受struct
{
内部静态只读int位;
静态组件()
{
位=组件。位计数器++;
}
}
用法:

var pos = new Position(x, y);
var bit1 = Component.GetBit<Position>();
var bit2 = pos.GetBit();
var pos=新位置(x,y);
var bit1=Component.GetBit();
var bit2=位置GetBit();
是的,上面的代码编译并运行。从中看到它


注:我会考虑嵌套代码<代码>组件>代码> <代码>组件>代码> < /p>不使用继承。编辑:它看起来像是
组件
要用作int字典的类型。你可以做到。没有必要继承它。@Theraot我对你的评论有点困惑。这意味着我必须为我拥有的每个组件复制代码,不是吗?另一方面,我如何才能将变量识别为组件呢?编辑:我想第二个问题我可以使用接口IComponent。我认为没有必要重复。根据确定什么是组件。。。只需将每个结构视为一个可能的组件。如果程序员试图将结构添加到实体中,将任何结构添加到任何实体中(使用为此创建的任何API),那么它就是一个组件。编辑:然后使用类型查询位。@如果我理解正确,这意味着我需要手动将每个结构“注册”为组件,例如组件,以便设置位或使用单独的逻辑来处理此问题。我最初的想法是,只要一个新组件被实例化,所有这些都会自动完成。请参见问题中的我的编辑1。我想我得改变设计了。如果你愿意,你可以写一个我可以接受的答案(尽管我会等待进一步的建议)。
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();