If I understand your design, there is no need for the
GameObjectto know theFactorytype. The only case where aGameObjectwould need to access a factory is when it needs to create anotherGameObject, which is common for objects that spawn other objects. However, since you are already using an event system, you can just define an event type such as "create object". This way, theGameObjecttype can spawn/create other objects by firing an event, without knowing about the existence of aFactory.No, not a good idea to separate the
GameObjectsby "type", because,GameObjectis supposed to be an abstraction, if you start typing it, you loose that abstraction and create coupling. Also, this would not be scalable if you where to introduce another specializedGameObject"type". It would require changing the factory to add another container for this new type. OOP-wise, it is best to keep theGameObjectabstract.You can optimize search and management of the
GameObjectsby using a more efficient data structure. A scene graph or a quadtree can reduce the number of queries when dealing with a lot ofGameObjectsspread into a given space. Also, for the specific case of removal, you can delegate that task to theGameObjectitself. When the object is expired, make it fire an event: E.g.:new Event_RemoveObject(this)that passes itself as the event argument. When the event is handled, the event manager will know who to delete.If you want to design for scalability, it is best to avoid inheritance. Taking the
Treecase, other more specific kinds of trees don't need to be objects in their own right. You can use configuration parameters to define that. This is what is otherwise known as Component Based Design. Define the behavior of aGameObjectfrom the set of its components. This makes for a very flexible and extensible approach.Yes, you can use a C++
unionto define a Variant type.
This is an example I have used before:
union Data { void * asVoidPtr; bool asBoolean; int asInteger; float asFloat; char * asCString; Vector3 * asVector3; Vector4 * asVector4; }; // Plus an enum flag that tell which field of the // union is in use, e.g.: a "type tag" It should be enough if the parameters of your events are only primitive types and raw pointers. If you need more complex parameters like objects and smart pointers, then your best bet is to define andan abstract Event class and specialize it as needed.