EntityManager construction

Started by
4 comments, last by evolutional 19 years, 4 months ago
Hi all, Just wondering how everyone puts together their entityManagers - I'm at that stage where I'm playing around with a few new ideas, and want to get some criticism / comparisons. I have the following general structure, with obvious bits removed to keep it short:

class EntityManager
{
public:
  ProcessMessage(Message* thisMessage);
private:
  std::map<Handle, Entity*> entityList_;
};


class Entity
{
public:
  virtual void Render() = 0;
  virtual void Update() = 0;
  void ReceiveMessage(Message* thisMessage);
  void SendMessage(Message* thisMessage);  
protected:
  std::list<Message*> incomingMessages_;
  std::stack<Action*> pendingActions_;
};


class EntityBuilding : public Entity
{
public: 
  void Render();
  void Update();
private:
  // Building type data, like position, dimensions etc.
};

class EntityMe : public Entity
{
public: 
  void Render();
  void Update();
private:
  // Me type stuff, like location, health etc.
};


Basically the entityManager just manages a map of Handles (which will probably be an unsigned int / smart pointer interface). It also receives message objects which can be sent by entities or other processes, and redirects them to the correct place. Message objects themselves are just a handle for who from and who to, as well as what they represent (with such descriptive enum terms as "HitYou" and "GoThere") and associated data. The entities all derive from a base class and can basically only do 4 things: Render themselves Receive Messages - just pops the new message into incomingMessages_ Send Messages - sends a new message to the entityManager for redirection Update themselves - the main part of which is handling all messages currently in the incomingMessages_ list, adding new actions to pendingActions_, and then dealing with the highest priority pendingAction_. Hope that's all clear - look forward to any comments / criticisms / comparisons. Jim. Edited as I made something private that should have been protected! [Edited by - JimPrice on November 24, 2004 1:53:38 PM]
Advertisement
The basic design is in the right direction, but there's on very neat little thing you can do that will throw things up a level.

Research pluggable class factories. There'sa good tutorial on GDNet here that you should read, as well as several other articles around the net.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Thanks Promit, really useful article. Rating++.

No-one else with any comments?
Jim.
I've been playing with something similar in a testbed environment. My entity class is:
* A state manager; each entity can have a state (defined by functors) and the Entity itself will allow transitioning from one state to another
* A message processor; the entity is extensible via functor-based message handlers, allowing new messages to be added to inherited classes with little pain. Message handlers can also be assigned/removed at runtime if needed.
* Hierarchical; the entity can be a child of another entity. Rather than have an EntityManager class, I have a single base entity to which all first layer root entites are attached. This hierarchy allows messages to be cascaded down the entity trees, so a 'damage' message would be passed down and handled to all sub entities. Imagine a car receiving a damage message, the windows in the car are more likely to shatter as a result of this message but the bodywork is not.
* A propertyset; instead of requiring each entity type to be defined in code, the propertyset allows dynamic properties to be attached at any point (although mainly at creation). The Get/Set property interface allows direct interaction with the GUI, level editor and/or any other entities. This allows a single generic entity class to be specified at runtime, not compile time. Entities can also be serialised and bound to script more easily.
* (has) A flyweight component for media management; this allows the entity class to remain generic through multiple projects, with the only replecement being the flyweight component that deals with how the entity is rendered and resource managed

It's not complete, but my Entity class is pretty powerful already. There is a price for the flexibility in the speed; for example propertyset access is slower than raw variable assignment, but to me it's not a huge deal. Feel free to steal any of these ideas/concepts or ask me more information about them and where I drew my inspirations [smile]
Thanks evolutional.

Few questions:

Quote:
A state manager; each entity can have a state (defined by functors) and the Entity itself will allow transitioning from one state to another


So you use functors to define an FSM, is that correct? And the state dictates the actions available at that time for that entity?


Quote:
Hierarchical; the entity can be a child of another entity. Rather than have an EntityManager class, I have a single base entity to which all first layer root entites are attached. This hierarchy allows messages to be cascaded down the entity trees, so a 'damage' message would be passed down and handled to all sub entities. Imagine a car receiving a damage message, the windows in the car are more likely to shatter as a result of this message but the bodywork is not.


Interesting - I am doing a similar thing with my buildings, but anm trying containment instead of a hierarchy (so in your damage example, the message is passed to the building, which will then communicate to its contained objects). Then again, I've not implemented this yet, so I'll have to keep this in mind.


Quote:
A message processor; the entity is extensible via functor-based message handlers, allowing new messages to be added to inherited classes with little pain. Message handlers can also be assigned/removed at runtime if needed.


Similar again, implemented through my editor. This is mainly for my AI - so the action-set available to an entity can be customised at design time by picking out a set of modules. I'm playing with Utility-based action selection - what I'd like to have is the ability to provide each entity a set of possible actions, each of which has an associated utility curve based upon a number of criteria, with specifiable parameters for the utility curves. For (a simple) example, an entity may have 'Attack' as an action state (with a default set of behaviours), with utility = agression + (sigmoidA : utility curve for myDamagePotential) + (decreasing exponentialB : utility curve for my Health) , where agression and the parameters of the sigmoidA and decreasing exponential curves are specifiable and obviously give a compromise between willingness to cause and avoid damage.


Quote:
A propertyset; instead of requiring each entity type to be defined in code, the propertyset allows dynamic properties to be attached at any point (although mainly at creation). The Get/Set property interface allows direct interaction with the GUI, level editor and/or any other entities. This allows a single generic entity class to be specified at runtime, not compile time. Entities can also be serialised and bound to script more easily.


Yep - doing exactly the same thing. My editor has a 'Mutate Object' clicky, that allows customisation of an entity - whether it be creating a 'Big Beastie' from a 'Beastie', or attaching a different AI module to have an 'Aggressive Beastie'.


Thanks for your comments,
Jim.
Quote:Original post by JimPrice

So you use functors to define an FSM, is that correct? And the state dictates the actions available at that time for that entity?


Correct, each Entity is a FSM. The state functors (which can be embedded in inherited classes) can be used for anything. Imagine a game entity that goes into "hibernation' mode, in my state transition I could stop the entity listening to certain messages or I could make it listen to more messages. For example, a 'wake-up' message would now need to be looked for. In a 'normal' state I could happily unhook the 'wake up' message as it's not needed, however I'd want to hook a 'hibernate' message to force the FSM to transition into the hibernation state.

Likewise, the state transition logic could also tweak properties; think of an RTS game where the tank is able to 'dig itself in'. Here it'd have two states, one being 'Normal' the other being 'Defensive'. The transition to/from normal would have a couple of effects:- Switching from normal to defensive would mean the tank would stop listening to any messages telling it to move, but at the same time, the 'Armor' and 'Hidden' properties would also gain a boost which in turn would affect how hard it is to hit the tank. Switching back would rehook the relevant messages and reduce the properties that were previously boosted.


Quote:I'm playing with Utility-based action selection - what I'd like to have is the ability to provide each entity a set of possible actions, each of which has an associated utility curve based upon a number of criteria, with specifiable parameters for the utility curves.


Interesting idea. I'd perhaps implement this in my system my making use of Utility functors that retrieve their values from the Entity's propertyset. This way, the propertyset is still tweakable which can affect how the utility function works. One thing I'm currently doing is binding my class with a script engine so that it would be possible to specify such things on the fly as it were. The utility function would then be a script with access to the propertyset. I'm also planning something similar for events, meaning that you'd be able to hook messages with a scriptable method - something like this would add great flexibility to the whole system I think.


Quote:
Yep - doing exactly the same thing. My editor has a 'Mutate Object' clicky, that allows customisation of an entity - whether it be creating a 'Big Beastie' from a 'Beastie', or attaching a different AI module to have an 'Aggressive Beastie'.


I like the sound of your system, mainly because when I was crafting my entity class I was bringing together a bunch of ideas from various books and resources (as well as adding my own). As I said, mine's still in the testbed stage (not added to any game) but if I used it, it would naturally be a foundation class in my games. It makes me happy that someone's implemented a similar system and is able to see it working well :)

This topic is closed to new replies.

Advertisement