I am attempting to create a code structure for a multiplayer game, of which I expect the codebase to become very large over time.
For now I am using blueprints, but for the future I would be open to using C++.
Currently my findings have been that creating dedicated controller blueprints works really well in organizing all code.
For example, a weather controller blueprint could manage time of day and cloud density.
And a traffic controller blueprint could manage the density of traffic, and make sure traffic seems equally spread across the map.
These are very helpful when creating a singleplayer game.
However, when switching to multiplay I find it difficult to have the controllers accessible for all clients and have them replicate their functions.
This is my current structure.
The GameMode will at BeginPlay check if the needed controllers are present in the game with a GetActorOfClass node.
If they can not be found, because maybe the level designer did not have need to change the default values for a controller, the GameMode will spawn them.
Then the GameMode stores these controllers in variables in the GameState, as it was my understanding that the GameState can be accessed by all.
Each controller would of coarse have many variables themselves, for the weathercontroller example that could be CloudDensity, CloudColour, WindDirection etc.
But since the GameState only stores a reference to the controllers it would still be clear and organized.
If however each controller had to have all of its variables also declared in the GameState, then it would end up with hundreds of variables.
It sounded good to me in theory, but I just cant get it to work.
If for instance I open an ingame menu with a widget blueprint on a client, I cant seem to access a function of a needed controller.
For example, a menu which allows me to change the time of day and access a ChangeTime function in the weather controller.
The server however can access the controller.
Taking a wild guess I suspect the variable stored in GameState refers specifically to the controller on the server.
And although it is replicated, the controllers on the clients do not link to this variable.
This is my guess because when in a client, getting the GameState, and then getting the variable with the controller, it turns up empty.
But the server does get a valid variable if it does the same thing.
Is this the correct way to go, or would you have a different approach?
If this is a valid structure, how would I store references to the controllers, and how would a client access functions of a controller through a widget?