Hiding Continue when there's no Save File

Hey! So I decided I wanted to go ahead and implement a little thing to my Main Menu by only showing the Continue button when there is a save file (so it’s inactive on the first playthrough).

So what I did was, inside the saving wrapper, I added a GetSaveFileBool() function that returns a bool. Inside the function I just have it, simply, return SaveFileExists(GetCurrentSave);

Then, in the MainMenuUI, I put a SerializeField Button, and I added a Start function. Inside Start, I set the continue buttons game object to set active depending on the savingwrapper’s funciton that returns if there’s a save file. It now turns on and off the continue button depending on whether or not there’s a save file.

Here are my edits if anyone wants to use it!

Saving Wrapper:

public bool GetSaveFileBool()
        {
            return GetComponent<SavingSystem>().SaveFileExists(GetCurrentSave());
        }

Main Menu UI:

[SerializeField] Button continueButton;

 private void Start()
        {
            continueButton.gameObject.SetActive(savingWrapper.value.GetSaveFileBool());
        }
3 Likes

Edit: Never mind! I was a video too early for these functions. Thanks!

1 Like

hi @Hairbearr @Mark_Lockwood can you provide the code of SaveFileExists
I can’t find this method in my script

It’s covered in the next video, but here’s my SavingSystem.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace RPG.Saving
{
    /// <summary>
    /// This component provides the interface to the saving system. It provides
    /// methods to save and restore a scene.
    ///
    /// This component should be created once and shared between all subsequent scenes.
    /// </summary>
    public class SavingSystem : MonoBehaviour
    {
        /// <summary>
        /// Will load the last scene that was saved and restore the state. This
        /// must be run as a coroutine.
        /// </summary>
        /// <param name="saveFile">The save file to consult for loading.</param>
        public IEnumerator LoadLastScene(string saveFile)
        {
            Dictionary<string, object> state = LoadFile(saveFile);
            int buildIndex = SceneManager.GetActiveScene().buildIndex;
            if (state.ContainsKey("lastSceneBuildIndex"))
            {
                buildIndex = (int)state["lastSceneBuildIndex"];
            }
            yield return SceneManager.LoadSceneAsync(buildIndex);
            RestoreState(state);
        }

        /// <summary>
        /// Save the current scene to the provided save file.
        /// </summary>
        public void Save(string saveFile)
        {
            Dictionary<string, object> state = LoadFile(saveFile);
            CaptureState(state);
            SaveFile(saveFile, state);
        }

        /// <summary>
        /// Delete the state in the given save file.
        /// </summary>
        public void Delete(string saveFile)
        {
            File.Delete(GetPathFromSaveFile(saveFile));
        }

        public void Load(string saveFile)
        {
            RestoreState(LoadFile(saveFile));
        }

        public bool SaveFileExists(string saveFile)
        {
            string path = GetPathFromSaveFile(saveFile);
            return (File.Exists(path));
        }

        public IEnumerable<string> ListSaves()
        {
            foreach (string path in Directory.EnumerateFiles(Application.persistentDataPath))
            {
                if (Path.GetExtension(path) == ".sav")
                {
                    yield return Path.GetFileNameWithoutExtension(path);
                }
            }
        }

        // PRIVATE

        private Dictionary<string, object> LoadFile(string saveFile)
        {
            string path = GetPathFromSaveFile(saveFile);
            if (!File.Exists(path))
            {
                return new Dictionary<string, object>();
            }
            using (FileStream stream = File.Open(path, FileMode.Open))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return (Dictionary<string, object>)formatter.Deserialize(stream);
            }
        }

        private void SaveFile(string saveFile, object state)
        {
            string path = GetPathFromSaveFile(saveFile);
            print("Saving to " + path);
            using (FileStream stream = File.Open(path, FileMode.Create))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, state);
            }
        }

        private void CaptureState(Dictionary<string, object> state)
        {
            foreach (SaveableEntity saveable in FindObjectsOfType<SaveableEntity>())
            {
                state[saveable.GetUniqueIdentifier()] = saveable.CaptureState();
            }

            state["lastSceneBuildIndex"] = SceneManager.GetActiveScene().buildIndex;
        }

        private void RestoreState(Dictionary<string, object> state)
        {
            foreach (SaveableEntity saveable in FindObjectsOfType<SaveableEntity>())
            {
                string id = saveable.GetUniqueIdentifier();
                if (state.ContainsKey(id))
                {
                    saveable.RestoreState(state[id]);
                }
            }
        }

        private string GetPathFromSaveFile(string saveFile)
        {
            return Path.Combine(Application.persistentDataPath, saveFile + ".sav");
        }
    }
}

The part you’re looking for is this:

public bool SaveFileExists(string saveFile)
        {
            string path = GetPathFromSaveFile(saveFile);
            return (File.Exists(path));
        }
1 Like

I think this does not update when the player deletes all the saved files. then go back to the main menu.

No, Start() only runs once. You could put it in OnEnable().

1 Like

Privacy & Terms