Search code examples
c++visual-studiotemplatesgame-engine

C++ | How to make a vector which contains multiple objects of different classes


I am trying to code my first game engine in C++ which will be like how Unity's scripting works. I am trying to make a component system. Here is my problem:

I want to have a vector containing my component since I will maybe need to add some dynamically. Where the problem happens is when I want to add derived class of my Component class. Here is an example:

std::vector<Component*> components;

With this line I cannot do this (which I would love to be able to do):

gameObject.GetComponent<TextRenderer>().text [...]

I still need to learn a lots and sincerely I do not understand totally the part of this (I don't understand templates and can't find a good tutorial) code but here is my GetComponent function:

template<typename T>
inline T* GetComponent()
{
    for (int i = 0; i < components.size(); i++)
        if (typeid(components[i]) == typeid(T))
        {
            std::cout << "Found Component." << std::endl;
            return (T*) &components[i];
        }
}

This function does not works it return nothing and/or have conversion problem.


Solution

  • I think that C-style conversion is undefined behavior.

    As far as I know, all the component class(like SpriteRenderer, Rigidbody and so on) derive from Component in Unity. So we can use dynamic_cast which offers safe downcasting. If the casting succeeds it returns a valid pointer otherwise nullptr.

    Here's an example of how I'd implement it.

    template<typename T>
    inline T* GetComponent()
    {
        for (int i = 0; i < components.size(); i++)
        {
            T* downcasted = dynamic_cast<T>(components[i]);
            if (downcasted)
            {
                std::cout << "Found Component." << std::endl;
                return downcasted;
            }
        }
        return nullptr; // Unity's GetComponent returns null when not found
    }
    

    And please also note that dynamic_cast is relatively slow, just in case you care about the performance really seriously.