0

I am trying to create a basic game engine in C++ and I want an Engine object to be able to loop through all the GameObject children to run their update methods, to do this I want to use a vector of all children within the Engine class.

For example:

This is similar to what I have been trying to do:

Parent Engine Class

class Engine {
public:
    Engine() {};

    std::vector<GameObject> GameObjects; //Vector to store all GameObjects

    void AddNewObject(GameObject& obj) {
        GameObjects.push_back(obj); //Add new object to the vector array
    }

    void Run() {
        for (int i = 0; i < GameObjects.size(); i++) {
            GameObjects[i].Update(); //Run the update method of each GameObject
        }
    }
}

GameObject Child Class

class GameObject : public Engine {
public:
    GameObject() {}

    void Update() {
        //Do stuff
    }

}

Main code loop

int main(void) {
  Engine engine;
  
  GameObject object;

  engine.AddNewObject(object); //Add object

  engine.run();
}

Any help would be greatly appreciated, Thanks.

Ken White
  • 123,280
  • 14
  • 225
  • 444
Parzivil
  • 3
  • 1
  • 4
    `GameObject` should probably not be a child of `Engine`. That implies that every single object in your game is in fact its own game engine, which is less than sensible. Aside from that and some possible [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) if you plan to subclass `GameObject` (which can be fixed with a good old-fashioned `unique_ptr`), I don't see any problems here. – Silvio Mayolo Nov 23 '22 at 01:29
  • 1
    be very cautios about storing objects in containers. it works but make sure you dont create copies. I have seen lots of code that has multilple copies of the 'same' object that are updatied into different startes. Better to put smart ptr into the vecto – pm100 Nov 23 '22 at 01:34
  • You have a plan. (Actually, I see two plans -- one involving "a vector of all children" and one involving a vector of addresses of all children.) So go for it. What's the question? Did you run into a problem? What are the symptoms? – JaMiT Nov 23 '22 at 01:39
  • @SilvioMayolo Thanks for the advice, I tried it out and it cut the number of errors in half, along with Brad 's advice it fixed the issue. – Parzivil Nov 23 '22 at 02:46

1 Answers1

2

There are a few issues here. First, your vector needs to be a vector of references or pointers, otherwise GameObjects.push_back(obj); makes a copy of obj to place into the vector (unless you move it) and polymorphism won't work (you can't hold subclasses of GameObject).

How you approach this depends on which object you want to own the memory associated with each GameObject. A trivial fix is is by using a vector of pointers:

class Engine {
    public:
        Engine() {};
    
        std::vector<GameObject*> GameObjects; //Vector to store all GameObjects
    
        void AddNewObject(GameObject& obj) {
            GameObjects.push_back(&obj); //Add new object to the vector array
        }
    
        void Run() {
            for (int i = 0; i < GameObjects.size(); i++) {
                GameObjects[i]->Update(); //Run the update method of each GameObject
            }
        }
    }

However, with modern, C++ you would want to probably use a smart pointer like unique_ptr:

class Engine {
    public:
        Engine() {};
    
        std::vector<std::unique_ptr<GameObject>> GameObjects; //Vector to store all GameObjects
    
        void AddNewObject(std::unique_ptr<GameObject> obj) {
            GameObjects.push_back(std::move(obj)); //Add new object to the vector array
        }
    
        void Run() {
            for (int i = 0; i < GameObjects.size(); i++) {
                GameObjects[i]->Update(); //Run the update method of each GameObject
            }
        }
    }

By using a unique pointer, you would have to change your other code:

int main(void) {
  Engine engine;
  
  std::unique_ptr<GameObject> object = std::make_unique<GameObject>();

  // Transfers memory ownership of `object` into `engine`
  engine.AddNewObject(std::move(object)); //Add object

  engine.run();
}

Lastly, your class hierarchy looks invalid. You probably don't need or want GameObject to be a subclass of Engine since they don't share anything in common. GameObject may likely be a good base class itself and other game objects would inherit it.

Brad
  • 10,015
  • 17
  • 54
  • 77
  • I took your advice of removing `GameObject` as a child of `Engine` and also fixing my issue of not making the vector a pointer. Seems to of fixed the issue. – Parzivil Nov 23 '22 at 02:48