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.