Super simple, just seems hard to understand
Let me explain:
GameMode: you have right, exist only on server. It is a secured actor which are hackproof because exist only on server, so clients cant modify it for example. But im sure many cause are there, why it is only on server
No matter, exist only on server. Gamemode is the actor who owns and controll all of your rules which your game need.
For example imagine a shooter game with Team DeathMatch Mode!
Gamemode will check scores, time and will decide when match is over and which team is winner!
Clear and simple right? But…
GameState: gamestate is a simplified actor which will replicate to every client. So Server will have one GameState and every Client will have a copy of that!!!
Because of replication you can use unreal engines networking in gamestate, replicate variables, call multicast rpcs and so on.
Why Gamestate is important?
Go back our TDM example. You have two team which have team scores. when team 1 achieving score GameMode should decide and add one point to team 1.
So basically scoring as i said below controlled on server by Gamemode.
But you want show that score on Client Uis right? For that you need GameState because GameState can replicate variable, so team scores should be stored in gamestate but only Gamemode can change it
Again clear right? For security reason we do not allow players to modify team scores, when someone dies we notify Gamemode this player died, Gamemode will decide we need add point for team or not, Gamemode modify point in Gamestate, Gamestate replicate score variable, Client Uis will refresh with new score
Gamemode and gamestate arent persistent actors, that means when you change level new gamemode and new gamestate will be spawned.
So if you load a brand new level gamemode, gamestates will be destroyed (client gamestates too) and when new map loaded new gm gs will be spawned.
Gameinstance actually is your game itself. Gameistance is persistent actor which will created when you first start the game and will be there as long your game runs.
No matter if you changing levels or players disconnecting from servers or go back to main menu, gameinstance will be there if game running.
Gameinstance is used for many cause like login and account check or giving informations about last played match or something.
Go back to our tdm example.
You want show some statistics for players after match ended, but you want to show that when new map is loading in background for example.
For this you can use gameinstance.
After match ended you send your statistics via gamestate and store in gameinstance, start load new level and you can use data from gameinstance, because gameinstance will be not destroyed
This GameInstance example isnt the best, but i hope you understand the point.