实体组件系统:渲染逻辑的放置位置

Posted

技术标签:

【中文标题】实体组件系统:渲染逻辑的放置位置【英文标题】:Entity Component System: Where to put rendering logic 【发布时间】:2016-05-10 11:36:48 【问题描述】:

我目前正在学习“实体组件系统”。 在阅读了许多教程和论坛帖子后,我仍然想知道渲染逻辑必须去哪里。我不是在谈论实际的 OpenGL/DirectX 渲染代码,例如,获取一个精灵并渲染它。我的意思是决定要渲染哪个精灵的逻辑。

一个可见的实体需要三个方面:

    评估 AI(改变位置、状态……) 评估呈现状态。例如,当实体在行走、攀爬、被击中时使用哪个精灵循环...... 实际渲染精灵

大多数教程建议使用类似 AISystem (1.) 的逻辑和 RenderSystem (3.) 来显示在 RenderComponent 中定义的精灵(循环)。他们没有说的是 在哪里 RenderComponent 被更新了。 我的理解是,将 (2.) 放入 (1.) 中,从而将字符逻辑与渲染逻辑混合在一起,是不好的设计。

直接的解决方案是为每个敌人添加一个特定的渲染逻辑系统。例如,对于 Gumba,我可以添加一个 GumbaLogicSystem、一个 GumbaRenderLogicSystem,对于实际渲染,可以添加一个所有基于 sprite 的实体都使用的通用 SpriteRenderSystem。然而,这意味着为每种实体类型创建两个组件*和两个系统,这似乎不是一个好的解决方案。

有没有很好的解决方案,在保持系统数量少的情况下分离字符逻辑和渲染逻辑?

谢谢

(* = 在一个简单的方法中,系统根据其组件处理实体。为了让 GumbaRenderLogicSystem 在实体上工作,它需要一个 GumbaRenderingLogicComponent 才能被系统识别。同样适用于字符逻辑。)

Edit1:我知道 ECS 是一种抽象模式。我的问题旨在针对如何保持系统数量较小的最佳实践。我的示例受游戏编程启发,但不限于该领域。让我用一个更抽象的例子来解释:

想象一下我有一些可见的实体。在基于层次结构的架构中,我会有类似的东西:

SomeModel(继承自 AbstractModel) SomeController(继承自 AbstractController) SomeRenderer(继承自 PixelRenderer,而后者又继承自 AbstractRenderer)。

在 ECS 中,我需要一大堆新类:

SomeModelSpecificDataComponent(即特定于该语义实体的数据) SomeModelSystem(执行逻辑) SomeModelSpecificRenderComponent(即呈现特定于该语义实体的数据) SomeModelSpecificRendererLogicSystem(决定如何渲染的系统) 像素渲染系统

有什么办法可以减少需要引入的新系统的数量?一种解决方案可能是添加“代理”或“行为对象”:一般 RenderingComponent 附加某个“RenderingAgent”类的实例,该类具有在 RenderSystem 中调用的单个方法“Update”。所以从技术上讲,组件本身并不包含逻辑。不过,我担心这可能是过度设计的。

【问题讨论】:

感谢您的提示,并为您的困惑感到抱歉。我添加了更合适的标签。 【参考方案1】:

经过一段时间的思考和多次讨论后,我意识到我的思维方式可能是错误的。我所描述的实际上适用于普通 ECS 方法。

防止系统和组件爆炸的唯一方法是对游戏元素提出适当的抽象,以便可以描述各种渲染需求 em>,而不是被编程。

我的意思是,例如,精灵引擎必须允许足够的抽象,您只能通过存储在渲染系统评估的渲染组件中的描述来表达各种动画和状态。您还需要做的是正确地将您的解决方案拆分为可重复使用的部分。

通过这种方式,ECS 比其他模式更能迫使您真正思考一个好的架构。

【讨论】:

当你说抽象时,你说的是继承吗?或者你真的了解this

以上是关于实体组件系统:渲染逻辑的放置位置的主要内容,如果未能解决你的问题,请参考以下文章

使用秋千渲染放置位置

如何在渲染不同组件时简单地嵌套三元逻辑

Entitas实现简析

在 SwiftUI 开始渲染 ContentView 之前,我们如何从 Views 中独立运行一些逻辑?

ASP.NET MVC 2 在哪里放置逻辑

三层架构分析