I need to clarify a few things you said:
I learned save my character stats to
the player controller and not the
player pawn as it will be destroyed
during level transfer and the
controller will likely stick around.
But now I need to save those variables
to game mode as the controller will
not carry over because the controller
needs to change for the battle
When changing level, all objects except the game instance will be destroyed and re-created. There are only two ways (in non-networked applications) to transfer data between maps.
The GameInstance remains persistant therefore any data stored within this class will be transferred between levels. However, I would highly recommend NOT overloading this class. I will explain a bit later about the purpose of each class.
Using a save object. Save objects are great for storing the types of data you mentioned. Not only can the data be transferred between levels, but also they can retain this data between application launches. I.e. someone can set the desired resolution and the next application launch can pick up that setting. If you don’t need data to be transferred between launches, you can destroy the slot on the application exit.
When you say “Game Persistence Level” I am assuming you mean the level blueprint for the persistent level.
There are a few reasons NOT to store everything here. It really comes down to understanding Unreals architecture for project setup. Each object has a purpose and we should assign the data we are working with the appropriate object. Here are some reasons:
Player and Game objects will get complicated very quickly in larger projects. Having all logic/data in one place will be a nightmare to maintain. Even more so, there it will be a pain to debug because its harder to track where this data is being set / accessed.
The larger the class / object, the longer it takes to compile and load. It can also have a heavy performance hit if these classes are making calculations they don’t need to.
Scope is important. When you get more experience and perhaps you start looking at the C++ side of things, you will be able to explore “private”. “protected” and “public” scoped data which drastically helps keep these classes organised.
Unreal Engine heavily adapted the Object Orientated Programming paradigms. By setting up classes appropriately you will eventually explore inheritance which is another brilliant way to help structure your projects and share data between classes.
I live by the rule “Objects should look after themselves”. If an object has no need for some data, it shouldn’t know about that data, It’s that simple. Using the built event systems you can really isolate each object and keep track of how your objects are performing, thus making debugging life simpler.
Lastly, I will give a quick break down of the major objects:
Game Instance: Control the rules for the application.
Game Mode: Control the rules for the level and manage controller objects.
Game State: Facebook profile for the Game Mode (networked applications)
Player Controller: Controls all the rules for the user, manage input, and any objects related to the user.
Pawn / Character: Represent controllers in the world (user and AI). Can be generated multiple times during a level.
Player State: Facebook profile for the Player Controller. (networked applications)
Player HUD: Control and manage UI
Persistent Level: Manage world objects and assist in creating relationships.
Bottom line, all this stuff you will pick with experience, when you start working with larger projects you will see the need for separating all data into the appropriate classes. I would highly recommend download projects released by Epic such as Robo Recall, so you can get a sense of how each of these objects should be utilized.
I hope this helps.