Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm in developing of isometric RPG with 3D characters on 2D level. I was trying to develop this using standard OOP paradigm, but face with a lot of issues. Recently i learned about ECS and found this conception fantastic! Currently i'm rewriting my engine using ECS paradigm, but one thing i can't understand, here's what:

I use OpenGL, and have two rendering systems - one for drawing 2d stuff and one for 3d. Each system consists of one VBO id, where appropriate geometry(2d or 3d) stored, shader program id, id of texture unit binded to texture atlas (which accommodates all the tilesets or all the model textures) and other stuff like that. These system provides different logic for drawing 2d and 3d stuff.

But the components for these systems - that's where i stuck.

Say, i have component, where are defined:

1)buffer offset from the beginning of VBO buffer

2)primitive count that needed to be rendered

Let's pretend that i have two instances of such component, but first instance belongs to level floor entity and describes the bunch of quad tiles, and second instance is a character mesh and belongs to the player entity. Ofcourse, first component instance should get in 2d rendering system, and second instance should get in 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 Graphics components, so both systems will take both component instances and one of these component will be processed improperly (2d Graphics component in 3d rendering system and vice versa)

So, 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 kinda clumsy.

Can you point me to my mistakes and provide a better solution, maybe?

share|improve this question
1  
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. – rickyviking Jan 14 at 23:29
    
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. – user2610005 Jan 15 at 11:55
    
@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. – ananas Jan 15 at 22:42
    
It's no different than having your Components inherit from a base Component class because they all need {common set of Component methods}. – ananas Jan 15 at 22:44
up vote 4 down vote accepted

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.

share|improve this answer

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.

share|improve this answer
2  
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 – user2610005 Jan 14 at 19:57
    
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 – DarioOO Jan 15 at 21:07
    
@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. – Miles Rout Jan 17 at 21:28
    
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 – DarioOO Jan 18 at 9:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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