Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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 am trying to design a typical (data-oriented) ECS engine. The issue I am struggling with is that my rendering system have to rely on two different sets of entities to actually do rendering.

My current idea is to have (usually one, but possibly more) entities representing cameras (e.g. sets of components describing views and viewports). Then, I can have CameraSystem that iterates through all CameraComponents and renders everything they 'see' to appropriate viewports.

However, this requires CameraSystem to query for two non-intersecting sets of components: cameras and renderables. My approach allows systems to select a set of nodes that have one or several required components. It does not allow for more complex queries, like either CameraComponent or RenderableComponent. This is not the first time when more complex system-component dependencies (using unions of component sets insetead of their intersections) seem useful to me, although I have never seen such an approach.

Plain old data components have crucial advantages:

  • They are trivially serializable
  • Can be changed by game designers without recompilation or coding knowledge
  • Describe behaviors in purely declarative way

That is why I would like to put cameras among other things in the ECS.

Use case: if we are implementing mirrors, we may put Renderable, Position and Camera components on them, then Renderable's texture will also be a render target for Camera. Camera/RenderingSystem then will render them in some efficient way. Systems (in my case) may or may not be mere interfaces to external libraries. They consist of update(dt, [nodes_to_update]) function, list of component names to query for (the point of my question) and, optionally, some state. They are just a uniform way of applying computation to game objects.

So, is defining more complex relations with components (like "this system should receive all nodes that have Camera and Position as 'cameras' collection and all nodes with Renderable and Position as 'renderables') the most convenient and flexible solution in this case, or is there a better way?

UPDATE: I ended up allowing systems to define their dependencies like this (the word "aspect" is borrowed from Artemis ECS framework):

aspects: {
    renderables: Aspect.all(['Transform', 'Sprite']),
    cameras: Aspect.all(['Transform', 'Camera']),
    emitters: Aspect.all(['Transform', 'ParticleEmitter']),
    ...
}

These lists are gathered, passed to a system, cached and rendered in an efficient way. This actually works quite nicely (in other systems too), as well as cameras being entities. Is this a common way to do it?

share|improve this question
    
If you solved your problem using the Aspect approach you describe, then feel free to elaborate on this in an answer and mark it as accepted. That makes it easier for people with similar problems to find your answer later. – DMGregory Jan 8 at 14:16
    
@DMGregory: I will wait for a few days and then accept or create an answer. Still, I would like to know whether my approach is common. – interphx Jan 8 at 14:29
    
Does being common make it better? If it accomplishes your goals within your performance targets and makes sense to you to use, then would it matter even if it was a one-of-a-kind solution? ;) – DMGregory Jan 8 at 14:31

First, you should not have a strict 1-1 mapping of Components to Systems. It's unclear to me from your question if that's the case already. You may very well have singular systems that use or interact with numerous components. Rendering, physics, AI, etc. are all Systems (they perform a cohesive set of updates and logic) but interact with many Components.

A System needs to be able to store a list of entities that match some particular Signature. e.g., if physics requires BodyComponent and TransformComponent, then the PhysicsSystem needs a list of all entities that have both of those two components.

Solution 1

A System also likely needs multiple such lists, as you're finding. RenderSystem needs to know about all Renderable+Transform pairs, as well as all Camera+Transform pairs, and that's only for a very simple rendering engine (once you get particles, post-processing, terrain, foliage, skinned meshes, etc. it gets more complex).

Solution 2

The other alternative that I'm rather fond of is to stop trying to use the ECS pattern. If you split all your engines (physics, graphics, AI, audio, etc.) up into separate libraries (which is probably already the case for physics since most people use off-the-shelf libraries there) then you'll note that you need each to exist independently of your ECS framework.

For instance, when you load an entity up and see that it has a PhysicsComponent you call into your physics library's CreateBody() function with all the data from the entity; that will usually return some kind of pointer or id. Store that into the PhysicsComponent. Most of the rest of the data you loaded off disk can possibly even just be thrown away since it'll all be copied into the physics library's internal data structures. Really all you're left with is some glue so when game logic needs to add a force to a game object it can find the appropriate pointer to the physics library's body object.

Your Components end up mostly just being glue that holds your convenient data-driven game objects together with the external handles/objects managed by your engine libraries. You're more likely to find that you don't need Systems at all anymore and possibly (for simpler games) don't even need Components, either.

Depending on your choice of libraries or how you decide to implement Components, this may still even end up looking a lot like an ECS. For instance, instead of storing a PhysicsComponent that holds a pointer to a rigid body object, your library may allow you to attach a unique ID to a body when it's created and then query for bodies by ID; that would allow you to attach the EntityId to the corresponding physics body and then write a ComponentMapper facade that queries your third-party physics library instead of a custom component data structure. I question the utility of such a design myself, but it's certainly something you could do.

share|improve this answer
    
It's probably not useful to post another answer saying to not use ECS for this, so I'll add my thoughts as a comment. If you imagine a scene graph for dealing with rendering, sound, etc., it's very easy to hook it up with an ECS; simply have a component that refers to or owns a node in the graph. The scene graph is the meat and bones of the world, while the ECS is the brain. – Boreal Jan 3 at 18:45
    
Thank you for your answer! Please, see my edits, I have clarified some details in my question. As system may need multiple lists of components/nodes, is it common or generally useful to implement simple DSL (possibly SQL-like) to handle such relations? Also, is signature a common word to refer to a subset of entity's components? – interphx Jan 4 at 11:13
    
@interphx: I'm unsure how common such a DSL is, though it sounds a little over-engineered to me. You perhaps could look around at any of the many open-source Entity Systems and see which one you like. – Sean Middleditch Jan 4 at 16:46

I think you are over-using the component model. While what you are saying could be accomplished and would work, the general way of doing this is making the camera a global thing.

Sometimes it is just much easier to make an exception than to try force everything into a rigid view of "everything must be a component". So I recommend making the camera not a component but rather a property of the RenderSystem. There you could even have a list of cameras, and the RenderSystem would have much more control to optimize the way things get rendered.


In response to your edit:

If you want to keep your original model, and you are willing to sacrifice performance(though that will depend on the implementation), you could do it in 2 passes. The first pass will only enumerate cameras into the system, and the second pass renders all objects from all viewports.

share|improve this answer
    
Please, see my edit. I have clarified why I believe that components are useful in this case. Also, I have some background in functional programming, from which I know that making things uniform brings big benefits for code quality, reusability and size. – interphx Jan 4 at 11:17
    
@interphx I still think its overkill, but see my edit. – akaltar Jan 4 at 13:05

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.