0

我目前正在开发一个实体组件系统变体,其中实体知道他们的组件。通常你访问这样的组件:

var camera = myEntity.Get<Camera>();

这样做的问题是,我希望某些对象始终具有某些组件并以类型和 null 安全的方式访问它们。而不是这样做:

if( !myEntity.Has<Camera>() )
    myEntity.Add<Camera>();
var camera = myEntity.Get<Camera>();

我宁愿使用:

var entity = World.CreateEntityWith<Camera,Position,...>();
var camera = entity.Camera;
var position = entity.Position;

我能想到的唯一方法是使用接口并实现如下:

public interface ICameraHoldingEntity
{
    Camera Camera { get; }
}

public interface IPositionHoldingEntity
{
    Position Position { get; }
}

public class CameraEntity 
    : Entity, ICameraHoldingEntity, IPositionHoldingEntity
{
    public World World { get; }

    public CameraEntity( World world )
    {
        World = world;
        Add<Camera>();
        Add<Position>();
    }

    public Camera Camera => Get<Camera>()!;
    public Position Position => Get<Position>()!;
}

这显然有一些缺点。如果有人删除了这个组件怎么办?如果添加第二个呢?

你能想出一种更聪明的方式或模式来实现我想要做的事情吗?而不是通过组合而不是通过继承?

感谢您阅读:)

4

2 回答 2

0

这真的是ECS吗?通常,您的大部分系统根本不应该通过实体,而是只需查询数据库中可用的所有相机组件(与它们关联的实体应该在很大程度上无关紧要)。

基于继承的解决方案与 ECS 相距甚远,并且失去了许多好处,如您的问题中所举例说明的,例如如果删除此类组件该怎么办。

如果您绝对必须在大量代码中获取以实体开头的组件,那么在您的设计中我能想到的最接近的事情是存储具有特定组件的实体列表。不是遍历所有实体来检查它们是否有摄像头,而是遍历预先存储的保证有摄像头的实体列表。并且您让您的 ECS 管理和更新那些具有摄像头的实体列表,因为添加和删除了摄像头组件。

于 2020-10-14T18:51:19.427 回答
0

我不是 100% 清楚整件事的含义。

如果泛型类型无论如何都可以基于属性在类设计中找到,为什么必须明确提及它们?

除了相应的模式之外,如果它只是关于最初创建的属性的分解命名,您现在宁愿在 C# 中使用流利的代码。

前任:

var world = World.Create().With<Camera>.With<Position>();

public World With<T>(you need something here?) where T :ISomeCommonality
{
   YourAdd<T>();
   return this;
}
于 2020-09-28T16:32:58.530 回答