I am currently working on my own little game engine and thought about implementing a simplified version of Unitys component system where you can attach objects of derived Components to an GameObject. Later you can request specific Components to use their functionality. Below is a stripped down (but still working) version of what I think about implementing.
#include <iostream>
#include <vector>
class GameObject;
class Component
{
private:
GameObject * parent;
public:
Component(GameObject * parent = nullptr)
{
this->parent = parent;
}
virtual ~Component() { parent = nullptr; }
GameObject* GetParent() { return parent; }
void SetParent(GameObject* parent) { this->parent = parent; }
virtual std::string What() { return "Basic Component"; }
};
class SoundSource : public Component
{
private:
// some sound specific members
public:
SoundSource(GameObject * parent = nullptr) : Component(parent) {}
virtual ~SoundSource() { }
std::string What() { return "SoundSource Component"; }
};
class GameObject
{
private:
std::vector<Component*> m_Components;
public:
GameObject() :
m_Components()
{}
~GameObject()
{
for (size_t i = 0; i < m_Components.size(); ++i)
if (m_Components[i]->GetParent() == this) delete m_Components[i];
m_Components.clear();
}
void AddComponent(Component* comp)
{
if (comp->GetParent() == nullptr)
{
comp->SetParent(this);
}
m_Components.push_back(comp);
}
template <class component_type>
component_type* GetComponent()
{
for (auto comp : m_Components)
{
component_type* c = dynamic_cast<component_type*>(comp);
if (c) return c;
}
return nullptr;
}
};
int main()
{
GameObject go;
go.AddComponent(new SoundSource());
go.AddComponent(new Component());
SoundSource *s = go.GetComponent<SoundSource>();
if (s) std::cout << s->What() << std::endl;
}
My initial plan for GetComponent<>() was to use the name of typeid to compare the component types, however since all components need to derive from the same base I think that using a dynamic_cast is the better option in this case. However I have never worked with dynamic casting before and I am not sure whether the way I use it is safe, so please tell me is it?
Also if you see any points for improvements I would appreciate your opinions.