Option 1 : replicate variables via RPC (parameters). Update variables on client when receiving the RPC, then do the processing. Make sure the RPC is reliable to avoid drops. With this, you don’t really need to replicate variables anymore, unless you need to support late-join replication, in which case you should enable rep condition InitialOnly.
Option 2 : put all variables that must “go together” into a struct, and replicate the struct, and use RepNotify instead of RPC.
Option 3 : if you have way too many variables for either option to be a solution, checksum sounds like a good idea.
Clients do not have a GameMode object, so for them the GameState would be an equivalent of it.
Having client-side game logic run off GameState’s RepNotify or Multicasts seems perfectly fine to me.