• 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
skwee

Component entity system - create from template

15 posts in this topic

Hi there!

 

I'm trying to implement Entity component system and I'm stuck with defining templates for entities.

 

My components are simply PODs (C++ structs/classes with public parameters).

Entity is simply uint-s.

 

Now I could do something like (pseudo-code):

Entity e = world.createEntity();
e.attach(new Component1(..));
e.attach(new Component2(..));
..etc 

But instead I want to define entities outside of the game code, probably inside JSON file, something like:

dog.json 
{
  "components":
  { 
    "sprite": .., 
    "anitmation": .., 
    ..etc 
  } 
} 

And then in the game (or scripting engine in JS) do something like

world.createEntity("dog", position); 

To do this, I need to have some sort of "Entity template". A list of all possible entities with all their components and their components initial data.

So at my games loading phase, I load all the needed entities and create templates from them, and then I can clone each template into its own instance of the entity.

 

One solution I could do, is to store the JSON in memory, and then on world.createEntity("name"); re-parse the json and create new entity with components.

But this would be inefficient (I guess) if I'm going to create many entities. I want to avoid parsing the JSON every time I create an entity.

 

I'm looking for some design pattern in C++ that would allow me to parse the JSON once, and store the parsed data somehow so that any next call to createEntity("name") would simply clone the already existing entity with as lower overhead as possible.

 

Unfortunately there is no information about entity templates/definitions in the web so I'm asking your help!

 

Thanks!

0

Share this post


Link to post
Share on other sites


I'm looking for some design pattern in C++ that would allow me to parse the JSON once, and store the parsed data somehow so that any next call to createEntity("name") would simply clone the already existing entity with as lower overhead as possible.

If you're after OOP patterns, then the Factory and the Prototype are possibilities. The entity services are asked for a new entity of type "dog". The services looks up "dog" in its entity prototype cache. If it is found, then the entity is cloned and returned. Otherwise the JSON reader is invoked, or perhaps the reader was invoked once at initialization time to fill up the services' cache a-priorily. However, the reader gets a map with all known components. The keys to the map are obviously the components' names. The values are factories for the belonging components, or else itself prototypes to the components. The reader builds a new entity accordingly to the JSON prescription and returns it to the entity services which itself place the result as entity prototype in its cache.

2

Share this post


Link to post
Share on other sites

Artemis uses entity templates, I think. At least the c# port example (Star Warrior) does. I haven't looked too closely at the implementation so I can't say much about it, but that might be a decent start if you want to see what other people are doing.

0

Share this post


Link to post
Share on other sites

Thanks for the replies!

 

haegarr

Thanks for mentioning the Prototype pattern! I learned something new today!

 

jms bc

Thanks, I heard about Artemis, and as far as I remember it is written in Java. Ill take a look into it.

 

simber

Thanks a lot! I've already though about clone method and CRTP.

 

However I'm still missing a link. Assuming my code is similar to what simber wrote (with the exception that I do not have Entity per se, its just a typedef to uint). 

In that case, assuming the code looks like this

Entity e = entitySpawner().spawn();
for(auto &comp: prototype) {
    entitySpawner.attach(e, comp->clone());
}

And assuming EntitySpawner knows about all the Component Systems, how do I register a component within a specific system?

In component based entity system, there are systems (or processes) that updates the components, I'm still not sure how I can introduce the needed components to the correct system in an elegant way.

 

Any solutions?

Edited by skwee
0

Share this post


Link to post
Share on other sites

The way I understand this type of actor component system is to have a map structure that accepts the string name of the component type and then accesses a factory function to return a new instance of that component (with specified parameters). 

 

So you would have a base type of "Component" and all your components would derive from this single type. Now you don't need to work with templates. Then your map would look like

map< String, Component>

This way you could just access them in your factory with some sort of function that only accepted a string.

Component* createComponent(string jsonString){
Component *comp = new map[jsonString.name];

//... extra stuff goes here for each different component

return comp; // return a pointer the a component and not the exact type of component
}
0

Share this post


Link to post
Share on other sites

EDIT: Err, where is the main part of my answer gone? Dammit! Half an hour gone down the drain...

 


In that case, assuming the code looks like this
Entity e = entitySpawner().spawn();
for(auto &comp: prototype) {
    entitySpawner.attach(e, comp->clone());
}
Edited by haegarr
0

Share this post


Link to post
Share on other sites


And assuming EntitySpawner knows about all the Component Systems, how do I register a component within a specific system?

In component based entity system, there are systems (or processes) that updates the components, I'm still not sure how I can introduce the needed components to the correct system in an elegant way.

 

You can explicitly add entities to systems like this (assuming Entity is just an identifier):

class System
{
public:
   void add(Entity e);

protected:
   std::vector<Entity> m_entities;
};

// update example
void MoveSystem::update(EntitySpawner& spawner)
{
   for( auto &e : m_entities )
   {
      Position& position = spawner.get<Position>(e);
      Velocity& velocity = spawner.get<Velocity>(e);
      position += velocity;
   }
}

Or you let the system query combinations of Components, no adding needed:

void MoveSystem::update(EntitySpawner& spawner)
{
   std::vector<Entity> entities = spawner.getEntitiesWithComponents<Position, Velocity>();
   for( auto &e : entities )
   {
      Position& position = spawner.get<Position>(e);
      Velocity& velocity = spawner.get<Velocity>(e);
      position += velocity;
   }
   
}

I used EntitySpawner here like you did , which may not be the best name for what it does.

 

These are only two incomplete examples, there are dozens of design possibilities for components and systems. For the second approach I can suggest to have a look at entityx .

0

Share this post


Link to post
Share on other sites

Thanks for the examples and reference to entityx (which I already checked), simber. However, it still doesn't fix my issue: How components are stored inside the spawner (or whatever we call it)?

 

Going back to your previous example

Entity e = spawner.spawn();
for( auto &comp : prototype )
{
   spawner.attach(e, comp->clone());
}

Lets continue with spawner, even though the name is incorrect and Ill probably add another class that will be responsible for storing the components.

 

First of all, how would attach() be implemented?

Second of all, how would getEntitiesWithComponents<X, Y ..>() be implemented?

 

I'm pretty weak with templates this why I ask.

 

[Edit]

I looked a bit into entityx. I see how they implement the component storage. They provide a family for each component. This is an elegant solution, you then can store all components in one list, instead of separating each component into its own list. What do you think about this approach?

 

Thanks a lot!

Edited by skwee
0

Share this post


Link to post
Share on other sites

For sure there are many ways of implementing a CES...

 

... but IMHO there is a design flaw in the above concept. A (so far) unknown object asks the spawner to spawn a new entity which seems to be just a UID. The spawner is hence a generator for UIDs. The said unknown object then iterates the component prototypes which are obviously already restricted to those belonging to the requested kind of entity. This iteration triggers cloning of the prototypes, and invokes the UID spawner to attach them to the entity. The "UID generator" is then responsible to drive the component collection?!

 

Another thing is this: Before going any deeper in code, you have to tell / decide how the entire system should work. Do you have an explicit collection of components that make up an entity? OP's statements "Entity is simply uint-s" and "Entity e = world.createEntity(); e.attach(new Component1(..));" contradict themselves. You said also that components are just data containers, and sub-systems are responsible for updating them. That allows the component instances to be stored with the belonging sub-systems instead of in entity oriented collections. Your question "how do I register a component within a specific system?" points in this direction. However the code snippets with "MoveSystem::update(EntitySpawner& spawner)" points to something else.

 

Obviously, how components are updated depends heavily on whether the one or other (or third) concept is chosen.

0

Share this post


Link to post
Share on other sites

haegarr

I agree with you.

 

Most of the code is pseudo-code and is in process of evolution. As I noted, spawner, or as you call it "UID generator", obviously should not care about storing and updating components, it only should be able to construct an entity. This was the initial concept of the EntitySpawner. It was then expanded by simber who suggest to use another class that will be responsible for storing the components and third class for each system, to update the needed components.

 

This question is also a theoretical discussion of different approaches to achieve the same. Whether there should be one system per component, or one "mega" system to store all components? What are the pitfalls of each approach?

 

I'm not so experienced in ECS and I need help and suggestions of those who know better than me, those we can see the pros and cons of each method.

0

Share this post


Link to post
Share on other sites

My favorite concept (because I'm about to implement it myself ;)) is the following:

 

An entity in the sense of a CES exists during runtime of gameplay only, i.e. it is part of the world. As such it is a UID and a couple of entries distributed over some sub-systems (named "services" in my engine). The entity instantiation process works on a resource kind of the Model class. A Model instance by itself is a composite of concrete Component instances. For each possible concrete Component sub-class there is a corresponding concrete ComponentType singleton-like instance. Such a ComponentType has a name (i.e. the one you use in JSON), is a factory for the belonging concrete Component, and can be understood as an outpost of one of the sub-systems.

 

Loading means to make Model instances, populate it with Component instances, and store them in the resource library. The ComponentType instances, addressed by their name, work as factories and de-serializer, so to say. The names of all used ComponentType instances are stored (indirectly) within the Model, too. There is another mechanism that may put objects into a Model instance. Components need not be specified in their entirety. Instead it is possible to express that some properties need to be defined at entity instantiation time (example: auto-generated individual name for each new instance of an orc-ish soldier).

 

Entity instantiation then means that the EntityServices sub-system is invoked to create a new entity by name. A parameter map is needed to be given at this moment if the Model of the requested entity has variables. The EntityServices creates a new entity UID, looks up the Model belonging to the given name in the resource library for Model instances, iterates the ComponentType instances for which a concrete Component instance is attached to the found Model instance, and invokes them to do their portion of entity creation. The entity UID, Model instance, and current Component instance is overhanded during this invocation. The ComponentType then investigates the Model instance for completeness, if necessary, does all allocation and initialization for the new entity inside the belonging sub-system, including eventually the filling of variables from the provided parameter map.

 

A ComponentType may return either with a Success, Failure, or Rework state. The former 2 are probably clear. However, it may happen that a ComponentType requires the set-up of another ComponentType (i.e. of another sub-system) to be done already, although those ComponentType wasn't iterated yet. So a ComponentType may tell the EntityServices that it want to be re-invoked once after the list of ComponentType is iterated first. What exactly happens within the sub-system during entity instantiation depends on the sub-system itself. It may be a cloning of Component as a prototype and linking the clone, or reserving and filling-in a place in a pre-allocated table, or whatever is suitable for the sub-system.

 

Notice please that the described mechanism doesn't require a 1:1 correspondence between sub-system and ComponentType; instead a 1:n correspondence is possible. Notice further that Component is just a data carrier, although it may define a behavior, but it does not perform any behavior.

0

Share this post


Link to post
Share on other sites

Looks similar to what I want to implement, but with different names for the classes. Thanks!

0

Share this post


Link to post
Share on other sites

A ComponentType may return either with a Success, Failure, or Rework state. The former 2 are probably clear. However, it may happen that a ComponentType requires the set-up of another ComponentType (i.e. of another sub-system) to be done already, although those ComponentType wasn't iterated yet. So a ComponentType may tell the EntityServices that it want to be re-invoked once after the list of ComponentType is iterated first. What exactly happens within the sub-system during entity instantiation depends on the sub-system itself. It may be a cloning of Component as a prototype and linking the clone, or reserving and filling-in a place in a pre-allocated table, or whatever is suitable for the sub-system.

 

Can you elaborate on this ("Rework")? Maybe some examples of what kinds of problems this is intended to solve? I don't have anything like this in my implementation, so I'm wondering if I'm missing something (or if I solved it another way).

Edited by phil_t
0

Share this post


Link to post
Share on other sites

Can you elaborate on this ("Rework")? ...

If the components are iterated in order C1, C2, C3, and the sub-system handling component C2 requires access to whatever C3 will cause later, then it will fail because C3 isn't handled yet. It then returns the Rework state to tell the entity services that it wants to be invoked again. The services memorizes all sub-systems that return Rework. After the initial run through all component the services iterates all memorized sub-systems and invoked them again. For the example, the total sequence then would be C1, C2, C3, C2. This is repeated (with resetting the memorized list each turn, of course) until at least one sub-system returned Failure, or none returned Rework, or the amount of Reworks was not lesser than as in the previous run (this last condition avoids endless looping).

 

The above is a mechanism to solve dependencies without a-priori bringing the sub-system invocations into a special order. It is perhaps not required for your implementation.

Edited by haegarr
0

Share this post


Link to post
Share on other sites

I would probably arrange things differently.. I will try to describe it with examples.

I would use Entities, Components, Nodes and Systems. Ok what are they..

 

Entity: Could be just a UID

Components: Things like a 3D-mesh component, visibility-component, location in 3d-space component, AI-component ..

Nodes: below..

Systems: Render System, AI-System, Pathfinding-System

 

When game data is loaded there are basically a set of components describing an entity. Like a mesh-component with the filename and the like and probably an ai-component. The component is only a set of values with some sort of identifier.

 

Then this set of components is examined. Means all systems check if they want an entity having this _combination_ of components. If the render-system sees a entity having a mesh-component and a visibility component it creats a render-node for this entity and stores this in a list, dictionary, vector or whatever..

 

On each frame each systems iterates over the nodes it has and does it`s work. If an entity looses a component the systems are notified about that and check if they have to destory/remove the respetive node (Or some other piece of code does this and only notifies the systems loosing a node/entity). For example if a entity looses its visibility-component the render-system may want to remove the render-node but the resources-system may want to keep its resource-node.

In pratice most system will need to share data. So the goal should be to try to group data as much as you can if the data is not shared by multiple systems, if data is shared by multiple systems, spread it in different components. The way systems will store the entites/component-sets will be different from system to system, most systems will probably use a simple list, others will use a different way cause they want to process the nodes with multithreading or have a search tree or whatever.

To identify if an entity has a set of components a component could have an integer-id and the check if a entity has a set of components could be done with bit-masking. (The check which is done when an entity is created and the systems want to know if they "want" this entity).

 

just my ..

avision

2

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