1

我想创建一个实体-组件-系统示例。我有像

internal struct Position : IComponent
{
    public int X { get; set; }
    public int Y { get; set; }
}

internal struct Movementspeed : IComponent
{
    public float Value { get; set; }
}

哪个实施

internal interface IComponent
{
}

在遍历组件时,我想尽快找到它们。我考虑过创建一个字典,将组件类型作为键,将组件作为值。

internal class ComponentCollection
{
    public ComponentCollection()
    {
        components = new Dictionary<Type, object>();
    }

    private Dictionary<Type, object> components;

    public void AddComponent<T>(T component) // add a new component
    {
        Type componentType = typeof(T);
        components.Add(componentType, component as IComponent);
    }

    public void RemoveComponent(Type componentType) // remove the component by type
    {
        components.Remove(componentType);
    }

    public bool TryGetComponent<T>(out T component) // get the specified component
    {
        try
        {
            Type componentType = typeof(T);
            component = (T)components[componentType];
            return true;
        }
        catch (Exception)
        {
            component = default(T);
            return false;
        }
    }
}

有两个问题出现。

  1. 如果有人使用float movementspeed并尝试添加一个新的 MovementspeedComponent 怎么办?拥有两个浮点数会引发重复键异常。我只能添加实现IComponent接口的自定义结构组件以防止重复。

  2. 当我尝试修改组件时,它们不会被引用修改

    private static void Main(string[] args)
    {
        ComponentCollection components = new ComponentCollection();
        components.AddComponent(new Position());
        components.AddComponent(new Movementspeed());
    
        if (components.TryGetComponent(out Position fooPosition))
        {
            fooPosition.X++;
            Console.WriteLine(fooPosition.X); // prints 1
        }
    
        if (components.TryGetComponent(out Position barPosition))
        {
            Console.WriteLine(barPosition.X); // prints 0
        }
    
        Console.ReadLine();
    }
    

有什么建议么?

4

2 回答 2

2

如果有人使用浮动移动速度创建一个新的移动速度组件怎么办

当我们每种类型都有一个对象/集合时,类型对键很有用,否则 aDictionary<Type, object>不合适,键应该是唯一的。

当我尝试修改组件时,它们不会被引用修改

由于所有组件都是structs 这行代码:

components.TryGetComponent(out Position fooPosition)

获取我们在字典中的结构的副本。来自C# 指南的引用:

结构在分配时被复制。将结构分配给新变量时,会复制所有数据,对新副本的任何修改都不会更改原始副本的数据。在处理值类型的集合(例如 Dictionary)时,记住这一点很重要。

如果有人使用浮动移动速度创建了一个新的 MovementspeedComponent 并尝试添加它怎么办?

于 2018-12-10T09:16:37.800 回答
1

我看到了 2 个解决方案。要么使用类而不是结构,要么添加一些更新方法来更新字典中的结构

public void UpdateComponent<T>(T component)
{
    Type componentType = typeof(T);
    components[componentType] = component;
}

然后在更新完结构后调用此方法:

if (components.TryGetComponent(out Position fooPosition))
{
    fooPosition.X++;
    components.UpdateComponent(fooPosition);
    Console.WriteLine(fooPosition.X); // prints 1
}

如果您将使用类而不是结构,那么您的旧解决方案应该可以工作。

于 2018-12-10T09:35:32.010 回答