3
\$\begingroup\$

I'm developing an isometric RPG, with 3D characters in 2D level. I was using a standard object orientated programming paradigm, but was faced with a lot of issues. Recently, I learned about entity component systems, and am currently rewriting my engine using this paradigm.

I use OpenGL, and have two rendering systems - one for drawing in 2D, and one for drawing in 3D. Each system consists of one VBO id, with the appropriate geometry, shader program id, id of texture unit binded to the texture atlas (which accommodates all tilesets or all model textures) and other information like that. The alternate systems provide different logic for drawing in 2D and 3D.

When it comes to the components for these systems, I am stuck.

Say I have component, defined by the buffer offset from the beginning of VBO buffer and the primitive count that needs to be rendered. Let's pretend that I have two instances of these components. The first instance belongs to the level floor entity, and describes the bunch of quad tiles. The second instance is a character mesh that belongs to the player entity. The first component instance should use the 2D rendering system, and second instance should use the 3D rendering system, but the data structure of these instances are identical. It must be said that I use EntityX and the components gets in the systems, automatically depending on their type.

Both systems require position and craphics components, so both systems will take both component instances, and one of these component will be processed improperly, what with a 2D graphics component in a 3D rendering system, and vice versa. I'm thinking about creating the "hollow" components, like sprite and model, which will indicate what graphics components in the entity mean. Since these component will not contain any properties, and would be used only as flags, this solution seems clumsy.

How do I better organise rendering in an entity component system?

\$\endgroup\$
  • 1
    \$\begingroup\$ Why are you using a single GraphicsComponent for both the 2d and 3d graphics items? Even though the data they contain is the same, they have a different meaning and should be 2 individual components. \$\endgroup\$ – rickyviking Jan 14 '17 at 23:29
  • \$\begingroup\$ Good point, i think it's the solution i need. I was just trying to avoid data structure repeating, but it seems like there is no other way. \$\endgroup\$ – user2610005 Jan 15 '17 at 11:55
  • \$\begingroup\$ @user2610005 - what you should try to avoid isn't so much data structure repeating, as data structure duplication - it makes perfect sense that, if two classes have the same characteristics, that they would share a common base class. Having two separate subclasses lets you add 2D or 3D specific data if you ever need it, and lets you avoid code smells like excessive conditionals. Tagging components make perfect sense -if- you need them for that purpose, but using them to determine the state of a different component is unnecessary overcomplication in most cases. \$\endgroup\$ – darkside Jan 15 '17 at 22:42
  • \$\begingroup\$ It's no different than having your Components inherit from a base Component class because they all need {common set of Component methods}. \$\endgroup\$ – darkside Jan 15 '17 at 22:44
4
\$\begingroup\$

From what I understand from your question, you have:

  • Two separate systems, 2D and 3D rendering
  • Each entity has a component describing the data needed for each system to operate
  • The systems require the same data structure, but operate independently of one another
  • You're looking for a clean way to differentiate the two components

While 1:1 mapping of Components to Systems isn't always ideal, in this situation, it makes sense to have two components (2DRenderComponent, 3DRenderComponent). You can have them use the same base code (e.g, RenderComponent is extended by both 2DRenderComponent and 3DRenderComponent), and just process the specific component with the relevant system. This prevents you from needing to use empty components to tag them, and makes it immediately obvious which is which (also allows you to have both 2D and 3D components for one entity, if you were to want that [e.g, a 3D model with a 2D representation for the mini-map]).

I agree that you shouldn't try to shoehorn your rendering into an ECS model, and that, ideally, the Components just hold pointers to actual primitives in the relevant render system itself - this allows your system to control and optimize rendering, without knowing/caring that it's inside of an ECS.

\$\endgroup\$
1
\$\begingroup\$

Most ECS systems are flawed by design (by flawed I mean it is just a mine opinion).

Usual way of doing things:

Entity.AddComponent<X>();
Entity.AddComponent<Y>();

This is flawed, because makes you need to add "hollow components".

Components should be added automatically by systems when entities register for them.

Alternative design:

SystemXK.Register(Entity);
SystemYZ.Register(Entity);

Advantages:

  • You do not query system from components, but you add components on systems, meaning that you can have 2 different entities, with the same component but working on 2 total different Systems.

The main reason why people use ECS is to allow easy serialization of entities in a DB, which is not possible in my alternative design (using it for personal projects only).

This is much better for code design because you actually decouple Components assemblation from systems. If you want an Entity in a system you just register the entity, then it is the system to provide the components.

I truly believe you should understand very well OOP before moving on ECS, and then you should really understand ECS too. Most ECS frameworks around are just "copy-cat" because "copying is cool", and all have their same design flaws. There are really few ECS frameworks authors that made some decent project. Or authors that try to understant, use, iterate and make something new.

Trying to implement your own ECS is good to start.

You do not need to make your rendering system necessarily a ECS, but you can make it usable through a ECS. If you have a plain OOP render system it is easy to wrap it in a Entity system, the opposite is very hard, so beware before ECS-ing your middleware.

\$\endgroup\$
  • 2
    \$\begingroup\$ I think, the main reason why people use ECS is not because of serialization but because OOP game object class diagram is turning into a mess like this : i.imgur.com/qtD5FZR.png \$\endgroup\$ – user2610005 Jan 14 '17 at 19:57
  • \$\begingroup\$ Yes the inheritance problems. Yes it is not one of the first thing they mention. Also solving a problem by composition does not necessarily require a ECS, so that's why I didn't mention that \$\endgroup\$ – GameDeveloper Jan 15 '17 at 21:07
  • \$\begingroup\$ @DarioOO The primary reason for using ECS is that when entities are integer offsets into arrays called components and systems are simply for loops, you get much better cache coherency. That's the point of ECS. Not serialisation. \$\endgroup\$ – Miles Rout Jan 17 '17 at 21:28
  • \$\begingroup\$ primary reason for using ECS the performance? "Wat"? I thought the main reason was to achieving perfect encapsulation, not performance. And anyway 90% of ECS systems I tried actually made performance worst. It is I think a urban legend, everyone mentions cache locality all the times without showing profiling :/. AAA games using naive ECS approach had all sort of tricks to avoid bad performance (like updating certain systems less often). Iterating the Whole memory in sequence is just a huge bandwith waste. one of main reasons should be the one mentioned by @user2610005 \$\endgroup\$ – GameDeveloper Jan 18 '17 at 9:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.