I'm working on a Game Engine (more like a Graphics Engine for Physics simulations) in C++. I know a bit of Unity and I like the concept of GameObject and Component Unity has and I wanted to use that in my project too.
The code structure at the moment is as it follows:
Newtonic::Engine: owns the scene, the engine's message bus and the engine's asset manager.
Newtonic::Scene: has shared_ptrs to actors (Actor is really what in Unity is called GameObject)
Newtonic::Actor: just an object in the scene. It has no property on its own, it's just a container for Behaviours that completely define how the actor behaves and how it is rendered onto the screen
Newtonic::Behaviour: abstract class that specifies how an actor behaves when updating game logic or when rendering the scene
Update and Render calls
Render the scene it calls
Newtonic::Scene::Render they in turn call the
Render methods on each actor in the scene and finally any actor calls it on any behaviour it has.
The assets manager
The assets manager (
Newtonic::Assets) owns all the resources the game needs and stores them in a
std::map<std::string, whateverresourcetype>. Resources can be accesed by their id from the assets manager that returns them as a
std::weak_ptr (so the ownership isn't shared with the code that requires the resource)
The message bus
This should be used to handle communications between separated parts of the engine. Like communications between the logic and graphics parts of the engine, but it still hasn't got a purpose.
Problems I'm having with this design
Newtonic::Behaviours need to have access to their parent
Newtonic::Actorand to their
Newtonic::Behavioursiblings (i.e. the other behaviours on the same actor). One possible way of implementing this would be that every Behaviour store a reference to their parent Actor, but this would create a circular dependecy issue as
behaviour.hwould need the definitions in
behaviour.hobviously. Although I know this can be done, it tastes like bad code design to do this and wanted to know whether I'm missing something myself.
Newtonic::Engineowns widely used parts of the engine like the assets manager and the message bus (in the future it should be used at least). But no other part of the engine can access
Newtonic::Engine, and again passing it to child stuff like Scene creates the circular dependency stuff.
Batched rendering. At the moment there is a
MeshRendererbehaviour that takes
weak_ptrs to a
Newtonic::Mesh. In the
Rendermethod this behaviour uses the shader with
glUseProgramand binds the mesh's VAO. The problem with this is that if I have like 1000
MeshRenderers that use the same mesh and shader they'll end up binding and unbinding shader and VAO 1000 times, which doesn't seem very performant. Here a solution might be using the message bus to schedule the mesh and shader rendering to a
BatchRendererobject (that should be owned by Engine I guess) and render after it all has been scheduled.
Code is at: https://github.com/ekardnam/Newtonic thanks for your time!