I have a base class Object
, and depending on how the object must behave on the scene, I have multiple abstract "role" classes, that inherits virtually from Object
:
Updatable
if the object is dynamic, and must be updated every frame;Collidable
if the object can collide with others, and thus must take part on collision detection;Drawable
if the object is visible and must be drawn.
So, for instance, a particle special effect animation is both a Updatable
, because it moves, and Drawable
, because it is visible, but is not Collidable
. A trigger may be Updatable
, but is definitely Collidable
, and is not Drawable
because it is invisible.
If objects are never removed or created, this design is easy to manage: I have three lists on my world, one for each object type, that hold pointers for all objects of that type: i.e. the updatable_list
holds a pointer to all my Updatable
s, etc. This is what I have so far.
Now I have to add and remove objects, and this design is biting me.
When a new object is added, I would have to use dynamic_cast
to figure out its roles and add its pointer to the proper lists. But dynamic_cast
is usually referred as bad design and code smell, not to mention being slow.
When an object is removed, it can potentially be part of multiple lists, so I would have to track its existence across lists, maybe by storing std::weak_ptr
instead of raw pointers, and would have to check and potentially remove every time I use an object from such list. Other options would be linear search and remove from all lists upon removal, or use std::unordered_set
instead of std::list
to make it fast to search and remove. But I find these other options a bit fragile, because I risk having dangling pointers if I "forget" to remove the object from some list.
So, my question, is this a good design? How can it be improved? How is this problem of different object types usually handled in game engines?
std::shared_ptr<Object>
who owns all objects. They are either created on initialization or during the update of some updatable object (i.e. some objects can spawn others). \$\endgroup\$ – lvella May 11 '20 at 3:55Object
only haveget_position()
,get/set_transformation()
,Drawable
hasdraw()
,Collidable
has bounding volume related attributes and funcions,Updatable
hasupdate()
. They don't have functions they don't need. \$\endgroup\$ – lvella May 11 '20 at 13:18