我想创建一个实体组件系统示例。我有类似
的组件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;
}
}
}
出现两个问题。
如果有人使用float movementspeed
创建一个新的MovementspeedComponent并尝试添加它怎么办?具有两个浮点数将引发重复的键异常。我只能添加实现IComponent
接口以防止重复的自定义结构组件。
当我尝试修改组件时,它们未被引用修改
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();
}
有什么建议吗?
答案 0 :(得分:2)
如果有人使用float创建新的MovementspeedComponent怎么办 运动速度
当每种类型都有一个对象/集合时,类型对键是好的,否则Dictionary<Type, object>
不合适,键应该是唯一的。
当我尝试修改组件时,不会通过引用对其进行修改
由于所有组件都是struct
的这一行代码,因此:
components.TryGetComponent(out Position fooPosition)
获取我们在词典中拥有的结构的副本。 来自C# guide的引用:
结构在分配时被复制。将结构分配给新结构时 变量,将复制所有数据,并对新副本进行任何修改 不会更改原始副本的数据。这对 记住在使用诸如以下类型的值类型的集合时 字典。
如果有人使用float创建新的MovementspeedComponent怎么办 运动速度并尝试添加它?
答案 1 :(得分:1)
我看到2个解决方案。使用类而不是结构,或添加一些Update方法来更新字典中的结构
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
}
如果您将使用类而不是结构,则旧的解决方案应该可以使用。