Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Systems in C++

In game development there is a notion of Entity System which is aiming to simplify the game loop by gaining a flexible architecture. For details see the links below:

http://www.richardlord.net/blog/what-is-an-entity-framework http://shaun.boyblack.co.za/blog/2012/08/04/games-and-entity-systems/

Now I wonder how it is possible to realize automatic Node creation when a Component is added to an Entity in C++? Please tell me the principle of identifying what Nodes can be spawned from a specific Entity, i.e. you should have list of Component and classes that aggregate components. And you should understand what classes can be created with the list of data.

For example I have Components:

class PositionComponent
{
  int m_x;
  int m_y;
  int m_rotation;
};

class VelocityComponent
{
  int m_vX;
  int m_vY;
  int m_vAngular;
};

class RenderableComponent
{
  Sprite m_view;
};

And nodes:

class MoveNode
{
  PositionComponent m_position;
  VelocityComponent m_velocity;
};

class RenderNode
{
  RenderableComponent m_rend;
  PositionComponent m_position;
};

Now if I create an Entity like this:

Entity * e = new Entity;
e.add(new PositionComponent);
e.add(new VelocityComponent);

Then I want to have a code that creates a MoveNode automatically, and if I add also this:

e.add(new RenderableComponent);

Then I want to know that also RenderNode is created. Consequently, when I delete it:

e.remove(new RenderableComponent);

the RenderNode should be deleted. And this process, of course, should not be bind to the specific Nodes and Components I have defined.

How is it possible to realize this in C++?

like image 659
Narek Avatar asked Jan 19 '14 20:01

Narek


1 Answers

I am slightly confused, since it appears to mix concepts. I will try to shed some light on the two concepts.

Entity & Component

The entity component system is quite common in game engines, for example Unity implements it quite visibly. It tries to address the issue that simple inheritance does not work well in many cases, such as mixing rendering and collision information; is a Collidable also a Renderable? And since multiple inheritance is a scary thing for many and not supported in many languages, the only way out of this is the Entity/Component design. (Actually not the only solution, but that is a different issue.)

The design for entity component is quite simple, you have a class Entity that takes multiple objects of type Component. There will be multiple components that "do" something, like a MeshRenderer, TriMeshCollision or RigidBodyMotion. As stated in the articles, the actual logic does not need to be implemented in the components themselves. The component just "flags" the entity for specific logic. It makes sense to delegate the actual work to be done in a tight loop in a system, maybe even in a different thread, but more to that later.

Then the actual entity is composed. There are two basic ways to do this, in code or in data.

For example you compose objects in code that represent one "real world" object; the object of type Goblin exists and it is derived from the class Entity. The constructor from Goblin will then create all components and register them on itself. Inheritance is now only done for high level logic, for example the FastGoblin is derived from Goblin and only has a different material and speed setting.

The second way to create objects is through data, that is you have some form of object description language. (Take something in XML or JSON) This will then create in a factory method something based on a given template in that is defined in this object description language.

Node Based Work Scheduling

It may make sense to have objects that are fully defined, but the logic not being executed. Think about objects on the server or in the editor. On the server you do not want the rendering code to be in the way. So the basic approach is to create components that contain no data. The problem to solve is, how do you efficiently get things done without iterating through the entire scene each frame and typecasting the objects around?

What your second link describes is basically a botched version of Designing the Framework of a Parallel Game Engine

There needs to be a way to schedule the work in an efficient way. The proposed solution is to have "nodes" that each do a specific task. The nodes are then scheduled, by submitting them to either a work scheduler or a specific system.

Take for example rendering. You have an entity and it has a MeshRenderer component. This component will create a RenderNode and submit it to the RenderSystem. Then when it is time to render the frame the RenderSystem will simply iterate over each RenderNode and call its display method. In the display method the actual rendering is done.

Alternatively the system, engine or entity can create nodes based on specific component configurations. Take for example physics. The Entity has the TriMeshCollision and RigidBodyMovement components. The PhysicsSystem seeing this configuration creates a RigidBodyNode that takes the two components as inputs and thus implements rigid body motion. Should the entity only have a TriMeshCollision component the PhysicsSystem would then create a StaticColliderNode to implement the behavior.

But like the construction mechanic for components from data, the nodes can also be created and attached to the entity through a factory function. This can be part of either the object definition or a rule based system.

Mapping this design into C++ should be straight forward. The rather difficult bit is to figure out a way how the different bits get connected; for example, how the MeshRenderer gets access to the RenderSystem so it can submit its RenderNode. But this can be solved with a singleton (shudder) or by passing a Game/Engine object around at the construction of the Entity or Component.

Is this good design?

But the issue I want to address here is: Is this good design?

I have troubles with your second link (Games And Entity Systems), since I think the design will fall flat on its nose quite quickly. This is true for other aspects like physics, but this will become quite inefficient when considering modern 3D rendering.

When you need to organize the scene spatially to efficiently cull hidden objects, organize the objects into batches for lighting and reduce resource switching then the entire "list of nodes" concepts is moot since you need a separate organisational structure anyway.

At this point you can let the components "talk" directly to the systems and each system has its own unique specific API that is fit for its specific purpose. The requirements of rendering, sound and input are each significantly different and tying to cram them into on API is futile.

See Also

  • Entity/Component based engine rendering separation from logic
like image 190
rioki Avatar answered Sep 18 '22 13:09

rioki