I have a pretty large class that runs all of the global logic/management tasks the game needs to function: it has a reference to the database containing stuff like the player and NPC stats & inventories, active quests, and the like. More importantly, it also takes care of routine tasks like changing the time of day, loading/unloading levels, cueing/exiting from cutscenes, and any other high-level game logic that doesn’t really belong in an object with a lower scope. When I created the manager class I made it a child of aactor, and handle accessing it by making the GameMode instantiate a new one into the persistent level at the start of the game and mapping it to a pointer, so anybody who wants to access it can do so through the gamemode.
It works perfectly, but I recently realized that I’m doing a lot of the same things that UGameInstance is supposedly intended to handle- am I right making it an AActor since it does quite a lot of heavy lifting to keep the game running, or should I reparent it to GameInstance?
UGameInstance is not replicated so that is something that may affect your decision. But to me it sounds like you could use the AGameState class since the purpose of it is to store the overall game state and it is replicated in case you need it to be in the future.
Hmm, I hadn’t thought of using GameState; I do need reflection, so that definitely helps… my biggest (and really, only) complaint with using an actor is that to ensure everything can get a reference to it at need, I have to use TActorIterator (I placed it in my GameMode) to find it at the start and set a pointer, after which anyone who needs to access it does so by accessing the game mode via GetWorld()->GetAuthGameMode(), then casting the result to my child class and looking at the pointer to AWorldManager. It’s not something so unperformant that it’s worth having nightmares over, but the clunkiness still bugs me on a pure aesthetic level.
I create them as sub-objects of the GameInstance since I don’t need mine to replicate (reflection != replication btw). They are UObjects in my case, not Actors. This is mainly because they need to exist before most objects in the world.
A lot of my managers however need the ability to get the current game world. The way I do this is have a ‘Prepare’ and ‘Release’ function. When a new map starts loading, we call ‘Release’ which sets the ‘CurrentWorld’ pointer to null. When the world has finished loading, we set that pointer again.
This is the most accesible and flexible way I’ve found of doing it so far. We wrote some static accessor functions so that they can be ‘gotten’ from anywhere. Really need to write up a tutorial on this system. I think it’s pretty nice…