Saving System No longer working between Scenes after Lecture 128

Hello, I have lately been having ALOT of issues with this savign system, and i just cannot get it to work how it is suppose to, and its really frustrating cause i cant progress with my game development at all untill this bug is fixed. I am currently on Lecture 137, and i Havent touched the Weapon classes or portals in a long time, but it was around changing over to the “Progression” Scriptable object that i found out something broke my entire saving system, and iv been sitting here for hours trying to narrow down whats breaking it

As it stands right now, if my Fighter.cs class saving script is even enabled my entire game will crash if i even try to step into a portal (it crashes when it tries to save). my error is " NullReferenceException: Object reference not set to an instance of an object "

. I had this error before, and i fixed it by moving my EquipWeapon function into the Awake(), so idk why it just dicided to break

My other issue, is the fact the saving system isnt even working in general anymore after the Implementation of the “Progression” object and i have no idea how to fix it or what is causing the issue.
The Savign system works(Minus the weapons), but something with the portals is completely busted. the stats save within the scene. So all my stats in Scene 0 will stay, and if i close the game and re open it, all my stats will load in like they are suppose to; however, when i go through my Scene 1, it dosent carry over any of my Stats from Scene 0. The two scenes are working copmpletely independant of each other. This is the savign for my Health.cs I have Dub lines to see in the console whats happening

. So if my health is 89.50% when i walk through the portal, it should Save that health, then load it into the new scene. however, when i load my Scene 1 im back at 100% HP. And this is what my console looks like. IDK why it runs so many times, and it never actually loads my health in the new scene. else it would say “Loading 179 healthpoints”. I dont understand why its savign 20 so many tiems back to back, thats the exact same debug line. I have noticed after some experimentation, that this is whoign the health of every character in my game, so that makes sense. nothing still carries between scenes This is the code for my portal. I have no idea whats breaking my game, but its very upsettign cause I have had so many issues with thsi savign system and i just cant figure out whats wrong with everything. Id appreciate help to get it working please. None of my Progression Carries over as i can be Level 2 in one scene, and Level 1 in another. These portals are also VERY inconsitent. all my portals are the exact same but some work and some dont, and sometimes it fully freezes my unity

To Sum most of this up, my main issue is nothing carries between scenes(save only within the scene), and my weapons dont save in general

Ok, before I chase the wrong rabbit… it appears moving the EquipWeapon into Awake has stopped it from crashing on Fighter() (based on the logs) or do you still have fighter disabled?

Wait, I think I see the problem in fighter…
image
should read

if(!currentWeapon==null) (the ! gets us every time)

The RestoreState() on the Health.cs issue doesn’t stand out as easily, though… Can you copy and paste your entire Health.cs script here (rather than screenshotting, which is difficult to read on all devices, you can type three ` symbols, (the backwards quote sign) in a row, paste the code after that, and type three more of them. It will format them for you here in the forum.

‘’'using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Saving;
using RPG.Stats;
using RPG.Core;
using System;
using RPG.Stats;

namespace RPG.Resources
{
public class Health : MonoBehaviour, ISaveable
{
[SerializeField] float healthPoints = -1f;
bool isDead = false;

    //used so other classes can tell if something is dead

    private void Awake()
    {

    }
    
    private void Start()
    {
        if (healthPoints < 0)
        {
            healthPoints = GetComponent<BaseStats>().GetStat(Stat.Health);
            print("Your HP is" + healthPoints);
        }
    }

    public bool IsDead()
    {
        return isDead;
    }
    public void TakeDamage(GameObject instigator,float damage)
    {
            //this takes whichever value is higher!
            //the difference between health and damage, or 0
            //stops the health from dropping below 0
        healthPoints = Mathf.Max(healthPoints - damage, 0);
        if (healthPoints == 0)
        {
            Dead();
            AwardExperience(instigator);
        }

    }
    private void Dead()
    {
        
        if (isDead) { return; }
        isDead = true;
        GetComponent<Animator>().SetTrigger("die");
        GetComponent<ActionSchedular>().CancelCurrentAction();    
        

    }

    private void AwardExperience(GameObject instigator)
    {
        
        Experience experience = instigator.GetComponent<Experience>();
        if (experience == null) { return; }

        experience.GainExperience(GetComponent<BaseStats>().GetStat(Stat.ExperienceReward));
        print("awarding exp" + GetComponent<BaseStats>().GetStat(Stat.ExperienceReward));

    }
    //used for saving
    public object CaptureState()
    {
        //  Dictionary<string, object> healthData = new Dictionary<string, object>();
        //   healthData["health"] = healthPoints;
        // healthData["dead"] = isDead;
        print("HP is" + healthPoints);
        Debug.Log("Saving " + healthPoints + " healthpoints");
        return healthPoints;
    }
    public void RestoreState(object state)
    {
       // Debug.Log(state);
        //  Dictionary<string, object> healthData = (Dictionary<string, object>)state;
        //  healthPoints = (float)healthData["health"];
        //  isDead = (bool)healthData["dead"];
        healthPoints = (float)state;
        Debug.Log("Loading " + healthPoints + " healthpoints");
        if (healthPoints == 0)
        {
            Dead();
        }
    }

    //getter functions
    public float GetHealth()
    {
        //the get component is essentially our max health
        return (healthPoints / GetComponent<BaseStats>().GetStat(Stat.Health)) * 100;

    }

}

}
‘’’

as for this change in fighter. changing it to if(!currentWeapon==null) actually hit me with alot more null errors, what i did to fix this was kepy my fighter the same, but in the CaptureState i added
if (currentWeapon == null) { return null; }
and that actually got my weapons saving again (still just in the one scene)

So as it stands, all my stuff is saving, and i can load my file and my stuff stays, its only when i go through the portal that nothing carries over

Ok, I understand why the health would be set back at 200 (because RestoreState() will always be called before Start()), but the fact that your Debug.Log("Loading "+ healthPoints +" healthpoints"); never fired is puzzling me.
The actual issue with the healthpoints will be addressed more completely in lecture 144, similar to Fighter, we have a Race Condition going on, the health is being restored before the health is set by Start(); Setting healthPoints in Awake() won’t work because BaseStats() relies on Experience which could also be in a race condition…
But you’ve already cleverly set a trap for that, by starting healthPoints at -1, so it’s only set when it hasn’t been restored… so why hasn’t it been restored…

Working through the logic of RestoreState(), like CaptureState() the system looks for all SaveableEntities, and then uses the UUIDs of the indexes to determine who should get what save information.
Try checking to see if the player’s IDs match in the SaveableEntities in both scenes… usually we want to manually set these both to “Player” and let the system manage the ID for the npcs.

1 Like

yeah i actually went ahead to that lecture to set up the health at -1 to try to fix this. However you did mention something i entirely forgot about in the code… the damn Unique Identifier… idk when i accidently reset that, but that was my issue. my saving is working how its suppose to between scenes now

damn, 5 hours of stress for it to be the identifyer

Thankyou very much, all this pain has taught me quite a bit and im happy to have it working again. thankyou very much!

It’s extra challenging when it’s not just the code that could be the problem. Dealing with inspector issues or Unity Quirks can add to the challenge.
Good job on the Initialization Trap, I was actually about to suggest it next when I saw you’d already put it in there.
In Lecture 144, Sam will introduce a resource called a “LazyValue”… Essentially, it does something very similar to what you did with the Init trap, only automaticaly.

1 Like

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