SavingWrapper LoadLastScene() causing Unity to crash please help

,

Hey all.

I am using the code as intended, and everytime I start the game or update the SavingWrapper.cs as stated then Unity freazes and stops working.

private IEnumerator LoadLastScene() {

        yield return GetComponent<SavingSystem>().LoadLastScene(defaultSaveFile);

        Fader fader = FindObjectOfType<Fader>();

        fader.FadeOutImmediate();

        yield return fader.FadeIn(fadeInTime);

    }

if I comment out :
//yield return GetComponent().LoadLastScene(defaultSaveFile);

Then it loads 100%…

Are there any error messages in the console window?

Looking at the heirarchy when the game starts running, is it continously cycling through loading and loading again?

Is Unity freezing completely (i.e. you have to force close it) or can you use the editor after stopping play with the play button?

Hi Brian,

I can’t look at the console, because unity freezes completely, I tried debugging as well, and it seems to go from the coroutine to getcomponent and then back to coroutine to getcomponent, it does not go passed it.

For interest sake I made the awake that starts the coroutine to start and that played the game but it was continuously reloading the game as I am loading the scene over constantly.

The play button just goes gray when I press it and then Unity does not respond when I do it.

Hmm… rather than playing 20 questions further on this (which I think in this case would be very frustrating, without easy access to the Console), go ahead and zip up your project and upload it to https://gdev.tv/projectupload
Be sure to remove the Library folder to conserve space.

Saving Wrapper Script

using System.Collections;
using RPG.Saving;
using UnityEngine;

namespace RPG.SceneManagement
{
    public class SavingWrapper : MonoBehaviour
    {
        const string defaultSaveFile = "saveFile";

        [SerializeField] float fadeInTime = 0.2f;
        
        private void Awake() 
        {
            StartCoroutine(LoadLastScene());
        }

        private IEnumerator LoadLastScene() {
            //yield return GetComponent<SavingSystem>().LoadLastScene(defaultSaveFile);
            Fader fader = FindObjectOfType<Fader>();
            fader.FadeOutImmediate();
            yield return fader.FadeIn(fadeInTime);
        }

        private void Update() {
            if (Input.GetKeyDown(KeyCode.S))
            {
                Save();
            }
            if (Input.GetKeyDown(KeyCode.L))
            {
                Load();
            }
            if (Input.GetKeyDown(KeyCode.Delete))
            {
                Delete();
            }
        }

        public void Load()
        {
            StartCoroutine(GetComponent<SavingSystem>().LoadLastScene(defaultSaveFile));
        }

        public void Save()
        {
            GetComponent<SavingSystem>().Save(defaultSaveFile);
        }

        public void Delete()
        {
            GetComponent<SavingSystem>().Delete(defaultSaveFile);
        }
    }
}

Saving System Script

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
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));
        }

        // PRIVATE

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

        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");
        }
    }
}

Double check your scene file(s) and make sure that there are no SavingWrappers present in the scene (before playing the game). The SavingWrapper should only exist in the PersistentObjectsPrefab which is loaded at runtime.
I suspect what is happening is that the scene is loading, reloading the last scene, which contains a SavingWrapper which immediately calls Awake(0 and loads the next scene. Because it’s in Awake and not Start(), the cycle never gets a breath, which is what may be locking the play button up.

Awesome, that made the game start!!!

Buttt now it is starting a lot of the same scene over and over and over. I am checking now in the console if I can see anything.

image

Ok nvm, sorry Brian, it is sorted now.

So the reason was indeed the persistant prefab that I still had in the scene.
And because of it reloading whole time, is because the previous save file was loading the previous persistant prefab and the new one at spawn.
So this got fixed after I deleted the old save file.

Thx so much!!

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms