1
\$\begingroup\$

I'm develping a 2d game (in XNA) and i've gone slightly towards a component-based approach, where i have a main game object (container) that holds different components.

When implementing the needed functionality as components, i'm now faced with an issue -- who should initialize components?

Are components usually passed in initialized into an entity, or some other entity initialized them?

In my current design, i have an issue where the component, when created, requires knowledge regarding an attached entity, however these 2 events may not happen at the same time (component construction, attaching to a game entity).

I am looking for a standard approach or examples of implementations that work, that overcome this issue or present a clear way to resolve it

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

While some people create multiple specialized Entity classes for instantiating different types of entities it's not a great idea. Usually the entity should not have to initialize components itself. It is composed and not in charge of composing itself.

Entities should be built and fully initiated during one step, which means you shouldn't have to build any additional components after the entity has been created. But if for some reason you think you need to initialize or setup components later, you might want to do that from a ScriptComponent.

To take this approach even further you could even use a dedicated InitComponent which could be discarded after its first use.


I think the most common method of generating entities is achieved with Factories.

Some people build entire entities from files (level loading, scenario loading...) or network messages using a data reader and multiple factories (abstract factory pattern).


In some engines components are initialized with an entity ID (not your case apparently):

GameEngine gameEngine = //instantiate here;
//...
int entityId = 1003;
//...
PhysicsComponent phy = new BulletComponent(entityId, ...);
ScriptComponent act = new EnemyScriptComponent(entityId, ...);

gameEngine.GetPhysicsSystem().Register(phy);
gameEngine.GetScriptSystem().Register(act);

When you register this component to your engine the ID is then used to link it to a given entity.

So when the actor component is registered it could need the current position of the entity to instantiate/define some behavior:

class ScriptComponent : public Component
{
    int entityID;
    ...
    void OnRegister(GameEngine gameEngine)
    {
        PhysicsComponent phy = gameEngine.getPhysicsComponent(this.entityID);
        phy.GetPosition();
        ...
    }
}       

The engine will call OnRegister on the newly registered component. You will want to make sure that your components can initialize properly by checking the order of the registrations or by delaying the call to OnRegister.


Another way of building components is to use a container entity (which seems to be your case):

GameEntity entity = new Entity(...);
//...
PhysicsComponent phy = new BulletComponent(...);
entity.addComponent(phy);

In this case the components registration to engines and unregistration is/could be managed by the GameEntity class.

In this case your entity can register each component and during registration your components will work the same way as in the previous example:

class ScriptComponent : public Component
{
    GameEntity entity;
    ...
    void OnAdded(GameEntity entity)
    {
        this.entity = entity
    }

    void OnRegister()
    {
        PhysicsComponent phy = this.entity.getPhysicsComponent();
        phy.GetPosition();
        ...
    }
}

In this case the OnRegister is called by the script system after the components have been attached to the entity. You can instantiate the desired behavior without worrying about the components registration order.


I for example never initialize any game related data in the constructor. Initializing components is done on Init(params...) this way I can preload them, reuse them, and init them one by one as data is loaded from a script, a file or from network.

\$\endgroup\$
5
  • \$\begingroup\$ Thanks. I was interested in how can i enforce that a given component initializes itself only after it was attached to an entity, since it needs some data from the entity (yes, in the strict approach the entity is only an id, but suppose it has a Position for the sake of the example, and my component needs to access that). According to your first example - how does the BulletComponent get that information then, if it was initialized (constructed) without respect to any entity? \$\endgroup\$
    – spaceOwl
    Nov 20, 2012 at 22:52
  • 1
    \$\begingroup\$ Why would the BulletComponent need that information? Perhaps whichever system using the BulletComponent should just directly access the PositionComponent of the entity. \$\endgroup\$ Nov 20, 2012 at 22:57
  • 1
    \$\begingroup\$ @liortal Updated my answer to cover that part. \$\endgroup\$
    – Coyote
    Nov 21, 2012 at 9:46
  • \$\begingroup\$ Thanks, this is very close to what i was looking for. The only thing i didn't get with 2nd example is why is the need for both OnAdded and OnRegister? what's the difference between the 2... \$\endgroup\$
    – spaceOwl
    Nov 21, 2012 at 17:56
  • \$\begingroup\$ @liortal OnAdded is called when the component is added to the entity. OnRegister is called when the entity is added (registered) in the system which will update the component. I use OnAdded to setup the component when needed (i.e. register for in entity messages and other non game related tasks). \$\endgroup\$
    – Coyote
    Nov 21, 2012 at 18:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .