C ++ component architecture

I am having trouble figuring out how to create a component based architecture in C ++. But I can't figure out a way to combine a vector of components with a class that comes from the component.

I want to override the virtual function of the components. But the only way to make it call the overridden function is to make the component class a pointer, but I want every game object to contain its own components in a vector, not outside the class like a pointer.

I tried to remove as much unnecessary code as possible.

My structure:

//GameObject class, contains components and other objects
class GameObject
{
public:

    GameObject(){}
    ~GameObject(){}

    void AddChild(GameObject child)
    {
       children.push_back(child);
    }
    void AddComponent(Component component)
    {
       components.push_back(component);
    }

    void Input(){}
    void Update(){}
    void Render()
    {
       for(unsigned int i = 0; i < components.size(); i++)
            components[i].Render();
    }

private:

    std::vector<GameObject> children;
    std::vector<Component> components;
};

//base class component
class Component
{
public:
    Component(){}
    ~Component(){}

    virtual void Input(){}
    virtual void Update(){}
    virtual void Render(){ cout << "Component -> Render()" << endl; }

};

class MeshRenderer : public Component
{
public:
    MeshRenderer(Mesh _mesh, Material _material)
    {
        mesh = _mesh;
        material = _material
    }

    ~MeshRenderer(){}

    //override components virtual Render()
    void Render(Transform transform)
    {
        mesh.Render(material);
        cout << "MeshRenderer -> Render()" << endl;
    }

private:
    Mesh mesh;
    Material material;
};

GameObject* root = new GameObject();
MeshRenderer meshRenderer(mesh, material);

root->AddComponent(meshRenderer);

//GameLoop
while(!quit)
{
   root->Render();
}

      

+3


source to share


2 answers


It looks like you want to pass your objects by reference, use

void AddComponent(Component& component);

      

to avoid slicing .


For proper use with std::vector<>

and polymorphic inheritance, you need smart pointers, e.g. std::unique_ptr<Component>

to retain ownership, or std::shared_ptr<Component>

to share (both raw pointers Component*

might work, but much more difficult to manage correctly).

void AddComponent(std::unique_ptr<Component> componentPtr); // Unique ownership

      

or

void AddComponent(std::shared_ptr<Component> componentPtr); // Shared ownership

      



and correspondingly

std::vector<std::unique_ptr<Component>> components;

      

or

std::vector<std::shared_ptr<Component>> components;

      

It depends on your actual use cases if these instances Component

need to be uniquely owned by their aggregating parent class GameObject

or not.


To use pointers std::shared<>

that might expire outside of their scope, you can use std::weak_ptr<>

.

As mentioned, it totally depends on your use cases and how you want these aggregated components to be accessible from outside the class GameObject

.

+1


source


It would be better if you could use unique_ptr

:

void AddComponent(std::unique_ptr<Component> component) {
    components.push_back(std::move(component));
}

std::vector<std::unique_ptr<Component>> components;

      



Thus, by calling AddComponent()

, you transfer ownership of the component to GameObject

.

+1


source







All Articles