Creating a Load/Save Game system in Unity


I won't go into too much detail about the Save Dialog window, since it can be created however you like, but here is a quick overview. The Save dialog is pretty basic and consist of a set of three Save (floppy disk) icons and a back option to close the dialog, with four corresponding hands.


I iterate through the save options using a List:

List<int> saveSlots = new List<int>{
   1,2,3,4
};

selectPreviousSave() and selectNextSave() are called for the left and right keys:

public void selectPreviousSave(){
  if(manager.GetComponent<gamemanager>().loadDialogIsShowing){
    saveSlotNumber--;
  }
  // If player tries to go past first entry/save slot, jump back to the last save slot
  if(saveSlotNumber < 0){
    saveSlotNumber = saveSlots.Count - 1;
  }
  chosenSaveSlot = saveSlots[saveSlotNumber];

I set the corresponding save slot hand to active and deactivate the other hands when an option is selected:

if(chosenSaveSlot == 1){
  // Save Slot 01
  saveHand01.SetActive(true);
  saveHand02.SetActive(false);
  saveHand03.SetActive(false);
  saveHand04.SetActive(false);
}

When a Save slot is chosen, I call chooseSaveOption(), which in turn calls SaveGame() on the chosen Save slot:


void chooseSaveOption(){
  if(chosenSaveSlot == 1){
    // Save Slot 01
    SaveGame(chosenSaveSlot);
  }
  ...

SaveGame() first checks that the current Save slot isn't full. If the Save slot is empty, it immediately writes the current checkpoint floor to the matching PlayerPref variable. If the Save slot is full, it displays a confirmation window to confirm that the player wants to overwrite the Save slot:

// Save the GameState parameters to the passed Save slot
void SaveGame(int saveslot){
  // Create a new GameState
  GameState gameState = new GameState(manager.GetComponent<gamemanager>().checkpointFloor, saveslot);
  // Check if the Save slot has already been saved to
  gameslotFull = gameState.CheckSaveSlot();
  if(saveslot == 1){
    // if gamestate already exist, confirm that the player wants to overwrite it
    if(gameslotFull){
      // Display Save Confirmation
      displayConfirmationWindow();
    }
    // If the save slot is empty, save to the slot
    if(!gameslotFull){
      gameState.SaveGameState();
      // Update Save slot text to display new saved floor
      saveSlot01Text.GetComponent<unityengine.ui.text>().text = "FLOOR " + manager.GetComponent<gamemanager>().checkpointFloor;
    }
  }
  if(saveslot == 2){
    // if gamestate already exist, confirm that the player wants to overwrite it
    if(gameslotFull){
      // Display Save Confirmation
      displayConfirmationWindow();
    }
    // If the save slot is empty, save to the slot
    if(!gameslotFull){
      gameState.SaveGameState();
      // Update Save slot text to display new saved floor
      saveSlot02Text.GetComponent<unityengine.ui.text>().text = "FLOOR " + manager.GetComponent<gamemanager>().checkpointFloor;
    }
  }
  if(saveslot == 3){
    // if gamestate already exist, confirm that the player wants to overwrite it
    if(gameslotFull){
      // Display Save Confirmation
      displayConfirmationWindow();
    }
    // If the save slot is empty, save to the slot
    if(!gameslotFull){
      gameState.SaveGameState();
      // Update Save slot text to display new saved floor
      saveSlot03Text.GetComponent<unityengine.ui.text>().text = "FLOOR " + manager.GetComponent<gamemanager>().checkpointFloor;
    }
  }
}

Each Save slot is created with an instance of GameState (a custom class):

public class GameState
{
  // Basic constructor for loading a saved game
  public GameState(int loadslot){
    this.loadslot = loadslot;
  }
  // Overloaded constructor for saving a GameState
  public GameState(int floor, int saveslot){
    this.floor = floor;
    this.saveslot = saveslot;
  }
}

CheckSaveSlot() checks if the matching PlayerPref variable (i.e. the checkpoint floor) is greater than 0, meaning it has been written to (the lowest checkpoint floor possible is 1).

If it's 0, saveslotFull is false. If it's greater than 0, saveslotFull is true.

The method returns saveslotFull:

// Return whether a GameState slot is already saved to
public bool CheckSaveSlot(){
  // Get the proper PlayerPref based on the saveslot passed in the constructor
  if(saveslot == 1){
    saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor01", 0);
  }
  if(saveslot == 2){
    saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor02", 0);
  }
  if(saveslot == 3){
    saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor03", 0);
  }
  // If the saved checkpoint floor is 0, then the save slot hasn't been written to
  if(saveslotStatus == 0){
    saveslotFull = false;
  }
  // If the saved checkpoint floor > 0, then the save slot has been written to
  if(saveslotStatus > 0){
    saveslotFull = true;
  }
  return saveslotFull;
}

SaveGameState() writes the current checkpoint floor to the corresponding PlayerPrefs variable:

// Save the checkpoint floor to the chosen Save slot
public void SaveGameState(){
  // Write to PlayerPrefs
  if(saveslot == 1){
    PlayerPrefs.SetInt("savedCheckpointFloor01", floor);
    PlayerPrefs.Save();
  }
  if(saveslot == 2){
    PlayerPrefs.SetInt("savedCheckpointFloor02", floor);
    PlayerPrefs.Save();
  }
  if(saveslot == 3){
    PlayerPrefs.SetInt("savedCheckpointFloor03", floor);
    PlayerPrefs.Save();
  }
}

Finally, to load a game, I create a new instance of GameState and call LoadGameState() on the chosen Save slot, which sets the checkpoint floor to the checkpoint floor of the corresponding PlayPref variable, and then starts the game on the selected checkpoint floor:

// Call LoadGameState() on selected GameState
void LoadGame(int loadslot){
  // Load Game State
  GameState gameState = new GameState(loadslot);
  gameState.LoadGameState();
  callHideLoadDialog();
  // Start the game with the checkpoint floor not set
  // to the PlayPref checkpoint floor for that slot
  PlayGame();
}
GameState.cs
// Set the checkpoint floor to the checkpoint floor of the current Save slot
public void LoadGameState(){
  manager = GameObject.FindWithTag("gameManager");
  // Read PlayerPrefs
  if(loadslot == 1){
    floor = PlayerPrefs.GetInt("savedCheckpointFloor01", 0);
    // Set checkpoint floor to checkpoint floor in GameState
    manager.GetComponent<gamemanager>().checkpointFloor = floor;
  }
  if(loadslot == 2){
    floor = PlayerPrefs.GetInt("savedCheckpointFloor02", 0);
    // Set checkpoint floor to checkpoint floor in GameState
    manager.GetComponent<gamemanager>().checkpointFloor = floor;
  }
  if(loadslot == 3){
    floor = PlayerPrefs.GetInt("savedCheckpointFloor03", 0);
    // Set checkpoint floor to checkpoint floor in GameState
    manager.GetComponent<gamemanager>().checkpointFloor = floor;
  }
}

Below is the complete GameState Class for reference:

Complete GameState.cs
public class GameState
{
int floor;
int saveslot;
int loadslot;
int saveslotStatus = 0;
GameObject manager;
bool saveslotFull = false;
  void Start(){
    manager = GameObject.FindWithTag("gameManager");
  }
  // Basic constructor for loading a saved game
  public GameState(int loadslot){
    this.loadslot = loadslot;
  }
  // Overloaded constructor for saving a GameState
  public GameState(int floor, int saveslot){
    this.floor = floor;
    this.saveslot = saveslot;
  }
  // Return whether a GameState slot is already saved to
  public bool CheckSaveSlot(){
    // Get the proper PlayerPref based on the saveslot passed in the constructor
    if(saveslot == 1){
      saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor01", 0);
    }
    if(saveslot == 2){
      saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor02", 0);
    }
    if(saveslot == 3){
      saveslotStatus = PlayerPrefs.GetInt("savedCheckpointFloor03", 0);
    }
    // If the saved checkpoint floor is 0, then the save slot hasn't been written to
    if(saveslotStatus == 0){
      saveslotFull = false;
    }
    // If the saved checkpoint floor > 0, then the save slot has been written to
    if(saveslotStatus > 0){
      saveslotFull = true;
    }
    return saveslotFull;
  }
  // Save the checkpoint floor to the chosen Save slot
  public void SaveGameState(){
    // Write to PlayerPrefs
    if(saveslot == 1){
      PlayerPrefs.SetInt("savedCheckpointFloor01", floor);
      PlayerPrefs.Save();
    }
    if(saveslot == 2){
      PlayerPrefs.SetInt("savedCheckpointFloor02", floor);
      PlayerPrefs.Save();
    }
    if(saveslot == 3){
      PlayerPrefs.SetInt("savedCheckpointFloor03", floor);
      PlayerPrefs.Save();
    }
  }
  // Set the checkpoint floor to the checkpoint floor of the current save slot
  public void LoadGameState(){
    manager = GameObject.FindWithTag("gameManager");
    // Read PlayerPrefs
    if(loadslot == 1){
      floor = PlayerPrefs.GetInt("savedCheckpointFloor01", 0);
      // Set checkpoint floor to checkpoint floor in GameState
      manager.GetComponent<gamemanager>().checkpointFloor = floor;
    }
    if(loadslot == 2){
      floor = PlayerPrefs.GetInt("savedCheckpointFloor02", 0);
      // Set checkpoint floor to checkpoint floor in GameState
      manager.GetComponent<gamemanager>().checkpointFloor = floor;
    }
    if(loadslot == 3){
      floor = PlayerPrefs.GetInt("savedCheckpointFloor03", 0);
      // Set checkpoint floor to checkpoint floor in GameState
      manager.GetComponent<gamemanager>().checkpointFloor = floor;
    }
  }
}

Files

elevader-v3.0.zip 44 MB
Jun 22, 2022

Get Elevader

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.