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++?
I am slightly confused, since it appears to mix concepts. I will try to shed some light on the two concepts.
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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With