Jump to content
  • Advertisement
Sign in to follow this  
The Communist Duck

Entity System?

This topic is 2910 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey.

I've been looking around at general architecture and designing stuff, and all the component based models I've seen go straight over my head. However, I was thinking and came up with something simpler, though I would like some feedback about if it's any good.

Basically:
Each entity has a vector of components.
Each entity has a method for common things, such as IsRenderable, which returns true if it finds a Renderable component or PhysicsComponent or whutever.
All the entities are defined at the start of running, either hardcoded, scripted, or xml'd or something and registered.

Pseudo:

class Entity
{
public:
bool IsRenderable() { return if found Renderable in components; };
bool IsPhysicsAffected() { return if found Physics in components; };
}

class EntityFactory
{
static void Register(string name, Entity* foo); //insert into map
static Entity* Create(string name);

private:
map<string, Entity*> entityTypes;
}

//somewhere else, probably in a global init() or something
//Simple hardcoded, rather than scripted for ease of showing.
Entity* foo1 = new Entity();
foo1.AddComponent<Renderable>().Init("mesh.md2"); //AddComponent<T> returns T
foo1.AddComponent<Random>().Init(100.f, true);
EntityFactory::Register("Foo1", foo1);

//etc.

Entity* foo = EntityFactory::Create("Foo1");




The components would register themselves to the subsystem, so the init() of Renderable would add that entity to a list of Renderable in the GraphicsSubsystem. If the flag notRender is true, for example, then it would remove itself from that list.

Of course, it's really not thought out well, but I wasn't sure.
I just wanted feedback, and hope it's a good idea. :P

Thanks for reading.

-Mark.

Share this post


Link to post
Share on other sites
Advertisement
Looks pretty standard. A few observations:

* You're relying a lot on string compares. Unique integral IDs for component types would be faster.

* Your design requires a per-possible-component member method in the Entity class. That's not too bad, but it's not necessary. A templated IsSomething<typename ComponentType> can access the component class' key and look it up from there.

* I don't see anything to actually access the components from each other, or even the Entity. How do components do what they need to do?

Share this post


Link to post
Share on other sites
I thought it seemed in-line with what I've read, but also seemed different. /confusing

(I think) Would something like a hashed string work for the unique IDs? It's used in Game Coding Complete, so I guess it should.

The templated idea looks better, thanks. :D

I didn't add anything to do with access yet, apologies.
Probably in the Init() method I would set component's parent Entity* pointer.

And for the most part, I planned on having the components to be registered with subsystems on creation if needed; so instead of having to do entity->Get<Renderable>()->Render(), the Renderer could just iterate its list and render them.

Guess the challenges are going to be implementing this and making a similar events system.

Thanks for the feedback. :D

-Mark.

Share this post


Link to post
Share on other sites
Quote:
Original post by The Communist Duck
(I think) Would something like a hashed string work for the unique IDs?

That depends on whether you're hashing the string on each lookup, or using the hash value for the lookup.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by The Communist Duck
(I think) Would something like a hashed string work for the unique IDs?

That depends on whether you're hashing the string on each lookup, or using the hash value for the lookup.


I would've said the latter. Replace std::string with (I believe) boost::hash_string or something?

Share this post


Link to post
Share on other sites
Well....
Quote:

bool IsRenderable() { return if found Renderable in components; };
bool IsPhysicsAffected() { return if found Physics in components; };

My first comment is get rid of this and make something more generic like, "IComponent *GetByID( componentId );". You are going to likely be adding several dozen components like "proximity detector", "explodable", "flamable", "particle emitter", "heat-seeking", "physics", "sound emitter", etc.
You don't want to be touching your entity system every single time you add some item you want to check for.

Quote:

Each entity has a vector of components.

Should probably be more like, each component has an array stored in some manager somewhere. Entities have a vector of < component ids,pointers to this array > . The manager keeps tabs on what indices in the array are "live", and knows to update them. This keeps all the data related to the components in one nice block of memory at the cost of creating a limit on how many instances of any one component you can have (though you can get around that with 'handles' instead of pointers)

Quote:

//somewhere else, probably in a global init() or something
//Simple hardcoded, rather than scripted for ease of showing.

Yeah. You definatly want to script+serialize this somewhere. I'd suggest breaking it up into a "entity template" script of some kind, instead of storing off a copy of a built entity. You will have hundreds of objects that contain the exact same components, but do entierly different things. Consider debris. You have a physics, timer, child spawner, spawnable, and render component on a debris. The specific settings, like "foo1.AddComponent<Renderable>().Init("mesh.md2");" would be 95% different for each of those components based on what was being shattered. You'd store off this static init data as a "entity form" description. The level data itself would consist of a "entity form id" and instance specific data.

For instance you could have something that looks like the following:
your "car debris" form would contain:

use template: debris
set renderable.model = "licence plate.md2"
set timer.default = 25.0
spawner.add( "spark_emitter" triggers on "physics_impact" )

while your instance data would contain:

set timer.value = 5
set physics.bouncy = 0.3
set physics.mass = 1.0

and your "entity template" ("debris") would contain:

has component physics
has component timer
has component child spawner
has component spawnable
has component and render

Share this post


Link to post
Share on other sites
Quote:
Original post by The Communist Duck
Quote:
Original post by Sneftel
Quote:
Original post by The Communist Duck
(I think) Would something like a hashed string work for the unique IDs?

That depends on whether you're hashing the string on each lookup, or using the hash value for the lookup.


I would've said the latter. Replace std::string with (I believe) boost::hash_string or something?


You could also use boost::uuid.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!