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
When Newtonic::Engine
should Update
or Render
the scene it calls Newtonic::Scene::Update
or Newtonic::Scene::Render
they in turn call the Update
or 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::Behaviour
s need to have access to their parentNewtonic::Actor
and to theirNewtonic::Behaviour
siblings (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 asbehaviour.h
would need the definitions inactor.h
andactor.h
already usesbehaviour.h
obviously. 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::Engine
owns 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 accessNewtonic::Engine
, and again passing it to child stuff like Scene creates the circular dependency stuff.Batched rendering. At the moment there is a
MeshRenderer
behaviour that takesweak_ptr
s to aNewtonic::Shader
and aNewtonic::Mesh
. In theRender
method this behaviour uses the shader withglUseProgram
and binds the mesh's VAO. The problem with this is that if I have like 1000MeshRenderer
s 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 aBatchRenderer
object (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!