• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
CRYP7IK

Component Based Entity System Question

12 posts in this topic

[font="Arial, sans-serif"][size="2"]Hey all, I would like your opinion on something...Okay so:

Say you have a component based entity system and your system is kind of normal:

Where an Entity is a ComponentContainer and an AttributeContainer.

Components are things that use attributes (The entity holds the attributes so that two components can say...access the Mesh attribute or health...) and can add\get attributes to an Entity.

Attributes are pretty obvious.

Now lets say you have your Renderable3D component, and when it gets added to an Entity or created you need it to also get added to the Renderer so it can be rendered...

How would you do this? Make the Renderer a singleton? (OnEntityAdded or Initialise on the component could then just add itself...)

[/size][/font][font="Arial, sans-serif"][size="2"]Or have a GameSystem that would hold a Renderer* and was a singleton?[/size][/font]
[font="Arial, sans-serif"] [/font]
[font="Arial, sans-serif"][size="2"]Or...? A solution without singletons!?[/size][/font]
0

Share this post


Link to post
Share on other sites
Why not construct the Renderer with a list of Renderables, inject the entity container into the Renderer so that it can request a list of renderables, subscribe the renderer to the entity system so that it listens for when a Renderable3D is attached, or any of a million other scenarios that don't involve singletons?
1

Share this post


Link to post
Share on other sites
My system is pretty similar to yours, but instead of the entities holding the attributes, components do. When another component requires the same attribute, it must say so when it's attached to the entity (via requirements). Anyways, I have a big entity system that consists of subsystems. Each subsystem handles ONE specific type of a component. The one system holds all renderables, the other one all collidables, and so forth. This way I can render all renderables "at once" (the subsystem obviously holds an entity => component dictionary) and do collision tests for all components in the other subsystem.

So basically you add one system per component (sometimes I do need a small hierarchy in components, so I've restricted my rule to having one subsystem per DIRECT subclass of component: all further subclasses are put into the same system). If you're interested, I can send you my sources.

1

Share this post


Link to post
Share on other sites
[quote name='CRYP7IK' timestamp='1316003860' post='4861521']
[font="Arial, sans-serif"][size="2"]Hey all, I would like your opinion on something...Okay so:

Say you have a component based entity system and your system is kind of normal:

Where an Entity is a ComponentContainer and an AttributeContainer.

Components are things that use attributes (The entity holds the attributes so that two components can say...access the Mesh attribute or health...) and can add\get attributes to an Entity.

Attributes are pretty obvious.

Now lets say you have your Renderable3D component, and when it gets added to an Entity or created you need it to also get added to the Renderer so it can be rendered...

How would you do this? Make the Renderer a singleton? (OnEntityAdded or Initialise on the component could then just add itself...)

[/size][/font][font="Arial, sans-serif"][size="2"]Or have a GameSystem that would hold a Renderer* and was a singleton?[/size][/font]
[font="Arial, sans-serif"] [/font]
[font="Arial, sans-serif"][size="2"]Or...? A solution without singletons!?[/size][/font]
[/quote]

I cheat. I have a method call on my entity class, which it delegates to all its components: void populateRenderList(MainRenderList list)

This way, on each frame, anything within the frustum is asked to add anything it wishes to the render list. This is highly useful for components which aren't normally drawn, but which I might want to draw something for debugging purposes.
2

Share this post


Link to post
Share on other sites
[quote name='CRYP7IK' timestamp='1316003860' post='4861521'][font="Arial, sans-serif"][size="2"]Now lets say you have your Renderable3D component, and when it gets added to an Entity or created you need it to also get added to the Renderer so it can be rendered...
How would you do this? Make the Renderer a singleton? (OnEntityAdded or Initialise on the component could then just add itself...)
[/size][/font][font="Arial, sans-serif"][size="2"]Or have a GameSystem that would hold a Renderer* and was a singleton?[/size][/font]
[font="Arial, sans-serif"][size="2"]Or...? A solution without singletons!?[/size][/font][/quote]Singletons are almost never the right solution, especially in high-level code like this.

The easiest way (IMO) to enforce this restriction ([i]"when it is created you need it to also get added to the Renderer"[/i]) is to require the renderer be passed to the constructor. In order to create a Renderable3D component, you need to have a reference to the Renderer ([i]which you should be able to pass around without resorting to global variables...[/i])
[code]class Renderable3D
{
public:
Renderable3D( Renderer& r ) : parent(r) { parent.Add( this ); }
~Renderable3D() { parent.Remove( this ); }

static void AddToEntity( Entity& e, Renderer& r )
{
e.AddComponent( new Renderable3D(r) );
}
private:
Renderer& parent;
Renderable3D();
Renderable3D( const Renderable3D& );
};[/code]

However, I'd prefer a simpler design that only has components and systems -- no attributes or even entities -- the game code can create it's own entities however it likes by grouping together component handles however it likes ([i]probably with entities being programmed in another language like Lua, rather than in C++[/i])[code]class RendererSystem
{
public:
int CreateRenderable()
{//some simple handle-based allocation, e.g.
int id = components.size();
components.resize( id + 1 );
return id;
}
private:
std::vector<Renderable3D> components;
};

struct MyRenderableEntity
{
MyRenderableEntity( RendererSystem& r ) : myRenderable(r.CreateRenderable()) {}
int myRenderable;
}[/code]
2

Share this post


Link to post
Share on other sites
[quote name='CRYP7IK' timestamp='1316003860' post='4861521']
[font="Arial, sans-serif"][size="2"]How would you do this? Make the Renderer a singleton? (OnEntityAdded or Initialise on the component could then just add itself...)

[/size][/font][font="Arial, sans-serif"][size="2"]Or have a GameSystem that would hold a Renderer* and was a singleton?[/size][/font]
[font="Arial, sans-serif"] [/font]
[font="Arial, sans-serif"][size="2"]Or...? A solution without singletons!?[/size][/font]
[/quote]

I've just been putting a first-attempt at an entity system into my wip over the last couple of days. It's probably got issues, and I've combined my attributes and component concept into one - but I've gone for a solution that allows me to do something like this:

[source lang="cpp"]
//Render all the ModelC components
ModelC::RenderAll(); //ModelC maintains all instances of its type and this function calls Render() for_each

//Add a ModelC to entity via one of several methods
entity->AddComponent(CID_MODEL);
//or
ModelC *model = ModelC::Create(entity); //the object is added to ModelC; we can safely let the newComponent pointer fall out of scope

//Access a ModelC for entity
ModelC *model = ModelC::Get(entity);
[/source]

The implementation relies on each component class simply having a static std::vector containing pointers to all instances of its type. So... yeah it requires static data, but not singletons, per se.
1

Share this post


Link to post
Share on other sites
[quote name='arbitus' timestamp='1316006036' post='4861531']
Why not construct the Renderer with a list of Renderables, inject the entity container into the Renderer so that it can request a list of renderables, subscribe the renderer to the entity system so that it listens for when a Renderable3D is attached, or any of a million other scenarios that don't involve singletons?
[/quote]

Those are all great ideas, however I still don't see how the user of my system will easily create an Entity that is able to be Rendered. Easy as in, oh I just give it a 3DRenderable component with a file name to a mesh and it is now being rendered at it's position! (Preferably they will also just be defining this entity in an XML file, or even further in an editor). I am leaning towards your third proposed idea, however that way the entity system will need to know about the Renderer so it can add a 3DRenderable if an entity is added with one attached to it...Yes?

If I was going to force them to get a Renderer pointer and give it to the 3DRenderable, how would I let them get that pointer?

Wow those are a lot of responses with a lot of good discussion material and they are making me re-think my current system! I will have to read and respond to them all later as it's 12:36 AM here in Brisbane and I have a meeting at 9:35 AM!

Thanks all! [img]http://public.gamedev.net/public/style_emoticons/default/biggrin.gif[/img]
0

Share this post


Link to post
Share on other sites
Each of my components have a component loader (simple factory), my entity factory has all these "loader" objects. The graphical one does whatever it need to (loading models, attaching things and what not) - it knows how to add things to the scene and so on. The component doesn't need to know these things (at some point it might). I can define my entities using xml like:

[code]<Entity>
<Components>
<Graphical>
<SceneNode>
<Mesh>
</Mesh>
</SceneNode>
</Graphics>
</Components>
</Entity>[/code]

The entity factory checks if it can load a given component type, if it can - then it goes ahead uses its sub factory to do so. As I'm using factories, once the entity factory is initially created, I do longer need to pass around anything like the scene/physics and so the factory can be used pretty much anywhere without problem.

My Graphical component just holds a "SceneNode" pointer, thats enough to do what I need with it (move the visuals mainly).
1

Share this post


Link to post
Share on other sites
[quote name='CRYP7IK' timestamp='1316003860' post='4861521']
[font="Arial, sans-serif"][size="2"]...
Lets say you have your Renderable3D component, and when it gets added to an Entity or created you need it to also get added to the Renderer so it can be rendered...

How would you do this?
...
[/size][/font][/quote]

The rendering system should own the renderables, and the entities should get [i][b]references to them[/b][/i] them [i][b]from [/b][/i]the rendering system.

This takes care of the registering-renderables-with-the-renderer issue. But it also allows the rendering system to manage the memory of the data it works with, so that it can process in a somewhat cache coherent way.


[quote name='CRYP7IK' timestamp='1316011065' post='4861567']
...the entity system will need to know about the Renderer so it can add a 3DRenderable if an entity is added with one attached to it...Yes?
[/quote]

Yeah, the components may handle all interaction with their respective systems, but at some level whatever code decides it needs one of those components to add to an entity will need access to those systems to either get the components or register them. Depending on how things work, this code may not actually live in the entity system.
1

Share this post


Link to post
Share on other sites
[quote name='SiS-Shadowman' timestamp='1316006709' post='4861535']
My system is pretty similar to yours, but instead of the entities holding the attributes, components do. When another component requires the same attribute, it must say so when it's attached to the entity (via requirements). Anyways, I have a big entity system that consists of subsystems. Each subsystem handles ONE specific type of a component. The one system holds all renderables, the other one all collidables, and so forth. This way I can render all renderables "at once" (the subsystem obviously holds an entity => component dictionary) and do collision tests for all components in the other subsystem.

So basically you add one system per component (sometimes I do need a small hierarchy in components, so I've restricted my rule to having one subsystem per DIRECT subclass of component: all further subclasses are put into the same system). If you're interested, I can send you my sources.
[/quote]

It is not completely obvious to me why a sub-system holds a dictionary of entity -> component (I assume by component, it is the actual component the sub-system deals with) that may be because:

A. My components can keep references to attributes that the entity has. (If you need position from the entity in the dictionary)
B. My components have a reference to the entity that contains it.

Do your components not know about their entities?

[quote name='speciesUnknown' timestamp='1316007796' post='4861542']
I cheat. I have a method call on my entity class, which it delegates to all its components: void populateRenderList(MainRenderList list)

This way, on each frame, anything within the frustum is asked to add anything it wishes to the render list. This is highly useful for components which aren't normally drawn, but which I might want to draw something for debugging purposes.
[/quote]

So the list gets given to the Renderer...how?

For example, lets say I was coding away in my GameState and I wanted to create an entity that is just a box that can be knocked around with physics:
(This is my current way, that I want to change from using singletons.)

[code]
Entity* myEntity = new Entity();
myEntity->AddComponent(new Renderable3D("box.mesh", true, Position));
myEntity->AddComponent(new PhysicsObject3D(meshBoundsShape, Weight));
[/code]


Now in those three constructors they each add themselves to each system, the Entity gets an ID from the GameSystem (Via singleton) and puts itself into the GameSystem the same way. The Renderable3D does the same with it's RenderSystem and same with the PhysicsObject3D...This makes it easy for a user of my system to create entities because things auto-magically go into their systems.

[font="arial, verdana, tahoma, sans-serif"][size="2"][quote name='Hodgman' timestamp='1316008017' post='4861544']
Singletons are almost never the right solution, especially in high-level code like this.[/quote]


Yeah, that's what I am trying to fix. My thinking that singletons fix everything![/size][/font]


[quote name='Hodgman' timestamp='1316008017' post='4861544']The easiest way (IMO) to enforce this restriction ([i]"when it is created you need it to also get added to the Renderer"[/i]) is to require the renderer be passed to the constructor. In order to create a Renderable3D component, you need to have a reference to the Renderer ([i]which you should be able to pass around without resorting to global variables...[/i])[/quote]

That's great and all, but then how does the user of this system access the renderer, do I have to force them to create it themselves in whatever state they want to render in?

Using your first example, contrasting to my above one:

[code]
Entity myEntity;
AddRenderable3DToEntity(myEntity, rendererThatIDontHaveHowDoIGetIt);
[/code]


would you then have to go:

[code]
Renderer* renderer = new Renderer(stuff);

Entity myEntity;
AddRenderable3DToEntity(myEntity, *renderer );
ChangeState("game", New GameState(), renderer); // Change state and pass in Renderer...
[/code]

I feel that is bad, because my user then has to worry about keeping his renderer available, which he may then just might make a global variable anyway...

[quote name='Hodgman' timestamp='1316008017' post='4861544']
However, I'd prefer a simpler design that only has components and systems -- no attributes or even entities -- the game code can create it's own entities however it likes by grouping together component handles however it likes ([i]probably with entities being programmed in another language like Lua, rather than in C++[/i])
[code]class RendererSystem
{
public:
int CreateRenderable()
{//some simple handle-based allocation, e.g.
int id = components.size();
components.resize( id + 1 );
return id;
}
private:
std::vector<Renderable3D> components;
};

struct MyRenderableEntity
{
MyRenderableEntity( RendererSystem& r ) : myRenderable(r.CreateRenderable()) {}
int myRenderable;
}[/code]
[/quote]

I kind of like this idea, but then how does the RenderSystem get to the game code where you are creating that entity? This is how I originally started doing this kind of system, however I didn't know how to make it data-driven and easily make it able to be scripted.

Man I am so confused now...
0

Share this post


Link to post
Share on other sites
Here's a very simple set-up that passes a renderer-pointer to the factory that is creating entities:[source lang=cpp]struct GameEngine
{
Renderer* renderer;
OtherSystem* blah;
};

class EntityFactory
{
GameEngine& engine;
public:
EntityFactory( GameEngine& e ) : engine(e) {}
Entity* LoadSomething(const std::string& file)
{
Renderer* r = engine.renderer;
....
}
};

class Game
{
EntityFactory factory;
public:
Game( GameEngine& e ) : factory(e) {}
};

int main(char** argc, int argv)
{
GameEngine engine = CreateEngine(argc, argv);
Game game( engine );
while(1)
{
game.Update();
game.Render();
}
}[/source]
1

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1316051150' post='4861842']
Here's a very simple set-up that passes a renderer-pointer to the factory that is creating entities:
[/quote]

Okay, I kind of see now...would it also be a good idea to allow someone to add entity types to the EntityFactory so that they could request that type again and get all the components added to it that the user specified?

And with this method, I will need a factory...for pretty much every system correct? Sound \ Physics \ Event \ Message \ Network \ State?
0

Share this post


Link to post
Share on other sites
[quote name='CRYP7IK' timestamp='1316049417' post='4861832']
[quote name='SiS-Shadowman' timestamp='1316006709' post='4861535']
My system is pretty similar to yours, but instead of the entities holding the attributes, components do. When another component requires the same attribute, it must say so when it's attached to the entity (via requirements). Anyways, I have a big entity system that consists of subsystems. Each subsystem handles ONE specific type of a component. The one system holds all renderables, the other one all collidables, and so forth. This way I can render all renderables "at once" (the subsystem obviously holds an entity => component dictionary) and do collision tests for all components in the other subsystem.

So basically you add one system per component (sometimes I do need a small hierarchy in components, so I've restricted my rule to having one subsystem per DIRECT subclass of component: all further subclasses are put into the same system). If you're interested, I can send you my sources.
[/quote]

It is not completely obvious to me why a sub-system holds a dictionary of entity -> component (I assume by component, it is the actual component the sub-system deals with) that may be because:

A. My components can keep references to attributes that the entity has. (If you need position from the entity in the dictionary)
B. My components have a reference to the entity that contains it.

Do your components not know about their entities?
[/quote]
Yes, in fact they do. This is because my entities don't have a list of components attached to them, instead the subsystems take care of that. I figured that I'll propbably never need to get ALL components of an entity, only a subset.


When creating an entity, it only references the entitysystem it has been created with. Upon adding a component, for examble your Renderable3D, the entity defers the call to the entity system, which in fact defers the call to the right sub-system. It will in return add the (entity, renderable) pair into it's dictionary.

[code]
Entity e = entitySystem.CreateEntity();
e.Add(alreadyExistingRenderable3DComponent);
[/code]

I solved the attribute problem by allowing components to reference other components, in fact, each component type specifies a Template that describes what this component actually requires. For example a renderable would require a transformable (everything that can be rendered must have a translation). This requirement now changes the process a bit. Upon adding the Renderable component, the entitysystem verifies that ALL requirements are met and if they are, the component is added. Otherwise an exception is thrown, containing all requirements that are not met. (The same procedure is done upon removing a component).

[code]

Entity e1 = entitySystem.CreateEntity();

e1.Add(new Transformable());

e1.Add(new Renderable3D());

Entity e2 = entitySystem.CreateEntity();

e2.Add(new Renderable3D()); //< throws because the transformable component is missing

[/code]

That very same template can be used to construct a component (because it is in fact a string => object dictionary + a list of required components) through a subsystem. My subsystems are not only responsible for calling update / draw on their components, the also serve as factories to create a component from a certain template. On top of that I have a template collection that describes an entire entity. This way I can create a template for a starship, store that template somewhere and finally create a thousand starships, only passing that template to the entity system.

[code]
var template = new EntityTemplate();
dynamic transformable = ComponentTemplate.FromType<Transformable>();
transformable.Position = new Point(10, 100, -15);
transformable.Orientation = new Quaternion(....);
dynamic renderable = ComponentTemplate.FromType<Renderable>();
renderable.Mesh = "bunny.x";
renderable.Material = "bla"
template.Add(transformable);
template.Add(renderable);

Entity entity = entitySystem.CreateEntity(template);
// Entity now contains 2 components (transformable and renderable)

// Both components will have all properties extracted from the template upon construction


[/code]

FYI: I'm using IronPython to describe all my components & entities, so I can simply redefine them while the game is running (and hence my c# example using the "dreaded" dynamic).

*edit* I forgot to mention that when retrieving a specific component from an entity, you specify it's type. The entity simply delegates the call to the entity system which in turn delegates it to the subsystem, responsible for that type (this method is mostly used upon entity creation and when components are attached):


[code]

Transformable t = e.Component<Transformable>();

Renderable3D r = e.Component<Renderable3D>();

[/code]

*edit2* So to sum it up, the ENTIRE state is kept in the entity system. All a user has to do is to have a reference to it. The entity system takes care of registering the components with the right sub-system. This way you don't need global access to the renderer because the right sub-system has access to it (because it was given the renderer during construction), no need for global access to the physics simulator because of the very same reason.


1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0