c++ - ECS框架如何更新组件数据并通知系统?

标签 c++ game-engine amazon-ecs

我正在使用 ECS 框架开发自己的游戏引擎。 这是我使用的 ECS 框架:

  • 实体:只是一个连接其组件的 ID。
  • 组件:一个存储纯数据的结构,根本没有方法(因此我可以编写 .xsd 来描述组件并自动生成 C++ 结构代码)。
  • 系统:处理游戏逻辑。
  • EventDispacher:向订阅者发送事件(系统)

但我对系统应该如何更新组件成员并通知其他系统感到困惑? 例如,我有一个像这样的 TransformComponent:

struct TransformComponent
{
    Vec3 m_Position;
    Float m_fScale;
    Quaternion m_Quaternion;
};

显然,如果可渲染实体的 TransformComponent 的任何成员发生变化,渲染系统也应该在渲染下一帧之前更新着色器统一“worldMatrix”。 那么如果我在系统中执行“comp->m_Position = ...”,RenderSystem 应该如何“注意到”TransformComponent 的变化?我提出了 3 个解决方案:

  1. 更新成员后发送一个UpdateEvent,并在相关System中处理该事件。这很难看,因为一旦系统修改组件数据,它必须发送这样的事件:

    {
        ...;
        TransformComponent* comp = componentManager.GetComponent<TransformComponent>(entityId);
        comp->m_Position = ...;
        comp->m_Quaternion = ...;
        eventDispatcher.Send<TransformUpdateEvent>(...);
        ...;
    }
    
  2. 将成员设为私有(private),并为每个组件类编写具有 set/get 方法的相关系统(将事件发送包装在 set 方法中)。这样会带来很多繁琐的代码。

  3. 不要改变任何东西,但添加“可移动”组件。 RenderSystem 将在 Update() 方法中迭代地对具有“可移动”组件的可渲染实体进行更新。这可能无法解决其他类似问题,我不确定性能。

我想不出一个优雅的方法来解决这个问题。我应该改变我的设计吗?

最佳答案

我认为在这种情况下,最简单的方法将是最好的:您可以只在读取/写入它的组件中保留一个指向 Transform 组件的指针。

我不认为使用事件(或其他间接方式,如观察者)可以解决这里的任何实际问题。

  1. Transform 组件非常简单 - 它不会在开发过程中更改。抽象访问它实际上会使代码更复杂,更难维护。

  2. Transform 是一个组件,它会针对许多对象频繁更改,甚至可能您的大多数对象都会在每一帧更新它。每次发生变化时发送事件都会产生成本 - 可能比简单地将矩阵/vector/四元数从一个位置复制到另一个位置要高得多。

  3. 我认为使用事件或其他一些抽象不会解决其他问题,例如多个组件更新同一个 Transform 组件,或者组件使用过时的转换数据。

  4. 通常,渲染器只是在每一帧复制渲染对象的所有矩阵。将它们缓存在渲染系统中毫无意义。

Transform 这样的组件经常被使用。使它们过于复杂可能会在引擎的许多不同部分出现问题,而使用最简单的解决方案(指针)会给您更大的自由度。


顺便说一句,还有一种非常简单的方法可以确保 RenderComponent 在更新后 读取变换(例如通过 PhysicsComponent)-您可以将工作分为两个步骤:

  1. Update(),系统可以在其中修改组件,以及

  2. PostUpdate() 其中系统只能从组件中读取数据

例如,PhysicsSystem::Update() 可能会将转换数据复制到相应的 TransformComponent 组件,然后 RenderSystem::PostUpdate() 可以只需从 TransformComponent 读取,没有使用过时数据的风险。

关于c++ - ECS框架如何更新组件数据并通知系统?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52947430/

相关文章:

c# - 二维游戏矢量运动 C#

c# - 尝试编写 C# 代码使导弹跟随 Unity 中的玩家

c++ - 使用 vector 存储实体

c++ - 如何正确地使用四元数进行旋转

c++ - 在不使用 C++ 中的虚函数的情况下从模板派生类访问方法?

c++ - 根据特定排序有效地从 map 中获取项目

amazon-web-services - 当 ECS_IMAGE_PULL_BEHAVIOR 设置为 Preferred-cached 时,强制 ecs-agent 拉取镜像

docker - AWS ECS任务:将卷装载到我的容器中会清除我复制的文件

docker - 如何在ECS代理容器上设置docker标签?

c++ - 三元运算符求值顺序