C#: playerprefs not loading or saving

Hi everyone

So I’m having this issue with PlayerPrefs not loading or saving as it seems.
I have been struggling with this and even looked up some examples but I think my issue might be the way it it set up I dunno. Maybe someone can have a look and tell me what I am doing wrong?

My script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SaveManager : MonoBehaviour {

    //Script refference
    public Experience experience;
    public PlayerHealth playerHealth;
    public LevelComplete levelComplete;
    //Bools
    public bool isLevelOneComplete = false;
    public bool DidloadOnce = false;
    //Variable to get shit working
    public float maxPlayerHealth = 100f;
    public int playerlevel = 1;
    public float expNeeded = 100f;
    public float currentExp = 0f;
    public int levelOneComplete = 0;



    public void SaveGame(){
        Save();
    }

    public void LoadGame(){
            Load();
    }


    void Awake(){
        experience = FindObjectOfType<Experience>();
        playerHealth = FindObjectOfType<PlayerHealth>();
        DontDestroyOnLoad(transform.gameObject);
    }

    void Save(){
         PlayerPrefs.SetFloat("MaxHealth", playerHealth.maxHealth);
         PlayerPrefs.SetInt("PlayerLevel", experience.playerLevel);
         PlayerPrefs.SetFloat("ExpNeeded", experience.expNeeded);
         PlayerPrefs.SetFloat("CurrentExp", experience.currentExp);
         if(levelComplete.LevelOneComplete == 1){
            PlayerPrefs.SetInt("LevelOneComplete", levelOneComplete);
         }
         Debug.Log("Saved");
    }

    void Load(){
        playerHealth.maxHealth = PlayerPrefs.GetFloat("MaxHealth");
        experience.playerLevel = PlayerPrefs.GetInt("PlayerLevel");
        experience.expNeeded = PlayerPrefs.GetFloat("ExpNeeded");
        experience.currentExp = PlayerPrefs.GetFloat("CurrentExp");
        levelComplete.LevelOneComplete = PlayerPrefs.GetInt("LevelOneComplete");
        Debug.Log("Loaded");
    }
}

The debug goes off so I assume the script completes but nothing happens. Any help would be appreciated and happy holidays everyone :smile:

I’m still waking up but, I’m not seeing where you are setting any values. For example, you declare and define maxPlayerHealth but you don’t assign it to playerHealth.maxHealth. Does playerHealth.maxHealth have a value yet that is being set somewhere else that I’m not aware of? Same goes for the rest of them.

Otherwise it looks like it should work.

bah those you can ignore they were mainly for testing and are not used. These are all the scripts that the save script points to.

Save script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SaveManager : MonoBehaviour {

    //Script refference
    public Experience experience;
    public PlayerHealth playerHealth;
    public LevelComplete levelComplete;
    //Bools
    public bool isLevelOneComplete = false;
    public bool DidloadOnce = false;
    //Variable to get shit working
    //public float maxPlayerHealth = 100f;
    //public int playerlevel = 1;
    //public float expNeeded = 100f;
    //public float currentExp = 0f;
    //public int levelOneComplete = 0;



    public void SaveGame(){
        Save();
    }

    public void LoadGame(){
            Load();
    }


    void Awake(){
        experience = FindObjectOfType<Experience>();
        playerHealth = FindObjectOfType<PlayerHealth>();
        DontDestroyOnLoad(transform.gameObject);
    }

    void Save(){
         PlayerPrefs.SetFloat("MaxHealth", playerHealth.maxHealth);
         PlayerPrefs.SetInt("PlayerLevel", experience.playerLevel);
         PlayerPrefs.SetFloat("ExpNeeded", experience.expNeeded);
         PlayerPrefs.SetFloat("CurrentExp", experience.currentExp);
         if(levelComplete.LevelOneComplete == 1){
            PlayerPrefs.SetInt("LevelOneComplete", levelOneComplete);
         }
         Debug.Log("Saved");
    }

    void Load(){
        playerHealth.maxHealth = PlayerPrefs.GetFloat("MaxHealth");
        experience.playerLevel = PlayerPrefs.GetInt("PlayerLevel");
        experience.expNeeded = PlayerPrefs.GetFloat("ExpNeeded");
        experience.currentExp = PlayerPrefs.GetFloat("CurrentExp");
        levelComplete.LevelOneComplete = PlayerPrefs.GetInt("LevelOneComplete");
        Debug.Log("Loaded");
    }
}

Experience script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Experience : MonoBehaviour {

    public int playerLevel = 1;
    public float expLevelModifier = 1.5f;
    public float expNeeded = 100f;
    public float currentExp = 0f;
    /*public Image levelImage;
    public Sprite level1;
    public Sprite level2;
    public Sprite level3;
    public Sprite level4;
    public Sprite level5;
    public Sprite level6;
    public Sprite level7;
    public Sprite level8;
    public Sprite level9;
    public Sprite level10;*/



    // Use this for initialization
    void Start () {
       
    }

    public void Awake(){
        DontDestroyOnLoad(transform.gameObject);
    }
   
    // Update is called once per frame
    void Update () {
        if(currentExp >= expNeeded){
            currentExp = 0f;
            Debug.Log("Current EXP set to 0");
            playerLevel += 1;
            Debug.Log("Level Up");
            expNeeded = Mathf.Round(expNeeded * expLevelModifier);
            Debug.Log("EXP Scales");
            //player.maxHealth = Mathf.Round(player.maxHealth * player.healthModifier);
            //Debug.Log("Health Scaled");
        }

    /*    if(playerLevel == 1){
            levelImage.sprite = level1;
        }else if(playerLevel == 2){
            levelImage.sprite = level2;
        }else if(playerLevel == 3){
            levelImage.sprite = level3;
        }else if(playerLevel == 4){
            levelImage.sprite = level4;
        }else if(playerLevel == 5){
            levelImage.sprite = level5;
        }else if(playerLevel == 6){
            levelImage.sprite = level6;
        }else if(playerLevel == 7){
            levelImage.sprite = level7;
        }else if(playerLevel == 8){
            levelImage.sprite = level8;
        }else if(playerLevel == 9){
            levelImage.sprite = level9;
        }else if(playerLevel == 10){
            levelImage.sprite = level10;
        }*/
    }
}

The experience gets added from the enemy scripts but that should change a thing. Other than that its only suppose to save the values.

The playerhealth:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PlayerHealth : MonoBehaviour {
    //Player Health
    public float currentHealth;
    public float maxHealth = 100f;
    public float healthModifier = 1.5f;


    public EnemyDamageHandler enemy;
    public Experience experience;
    float curTime = 0;
    float nextDamage = 1;

    public AudioClip[] playerHitSound;

    void Start(){
        currentHealth = maxHealth;
    }

    void Update(){
    if (currentHealth > maxHealth){
        currentHealth = maxHealth;
    }
        if(experience.playerLevel == 1){
            maxHealth = 100f;
        }else if(experience.playerLevel == 2){
            maxHealth = 125f;
        }else if(experience.playerLevel == 3){
            maxHealth = 150f;
        }else if(experience.playerLevel == 4){
            maxHealth = 175f;
        }else if(experience.playerLevel == 5){
            maxHealth = 200f;
        }else if(experience.playerLevel == 6){
            maxHealth = 225f;
        }else if(experience.playerLevel == 7){
            maxHealth = 250f;
        }else if(experience.playerLevel == 8){
            maxHealth = 275f;
        }else if(experience.playerLevel == 9){
            maxHealth = 300f;
        }else if(experience.playerLevel == 10){
            maxHealth = 325f;
        }
       
    }

    void Awake(){
        experience = FindObjectOfType<Experience>();
    }

    void OnTriggerStay2D(Collider2D other){
        if (other.gameObject.tag == "Enemy" && curTime <= 0) {
            Debug.Log ("Damage");
            AudioSource.PlayClipAtPoint(playerHitSound[Random.Range(0, playerHitSound.Length)], transform.position);
            currentHealth -= enemy.zombieDamage;
            curTime = nextDamage;
        } else {
    
            curTime -= Time.deltaTime;
        }


       
           
        if(currentHealth <= 0){
            Die();
        }
    }


    void Die(){
        Destroy(gameObject);
    }
}

Those are the save script and the one it is suppose to save values of. Currently it doesn’t seem to be doing anything as it isn’t loading so i assume it probably not saving aswell. Note that the save and experience script is set in a preloaded scene and doesn’t get destroyed and from there they search for the needed scripts. I don’t know if i explained that properly :confused: But yeah don’t know if that has anything to do with it.

How are you actually triggering the Save?

Disregard…

I just set up a quick project and I’m getting output:

MaxHealth100
UnityEngine.Debug:Log(Object)
SaveManager:Load() (at Assets/SaveManager.cs:69)
SaveManager:Start() (at Assets/SaveManager.cs:45)

Had to check something. but yes, it does seem to be reading and writing to PlayerPrefs.

The loading and saving are done with UI buttons. I have them on selected buttons. I play the game do a level and then the game is suppose to save. I stop playing and start again but it doesn’t load. So it either doesn’t load in the editor or im just doing something wrong for it not to work :frowning:

EDIT: So it is working as expected for you then?

Your save and load code is working for me. So, I don’t think it’s that.

To test, what I did was add a void Start() to your SaveManager.cs and called Save() and Load() then output to Debug.Log what was being returned from PlayerPrefs.

Maybe you can confirm that your save and load code works then once that is verified, go to the next step? Once you know for sure that you can save and load then move to how and when they are being called and go from there.

You said that you are seeing your debug statements? so the UI buttons are wired ok.

Seems to be. :slight_smile:

Well I fixed it by dragging the exp script from the scene into the save script but now it is giving me an error.

NullReferenceException: Object reference not set to an instance of an object
SaveManager.Load () (at Assets/Scripts/SaveManager.cs:51)

Yeah, your Exp script object isn’t getting instantiated. So when you call: experience.playerLevel=PlayerPrefs.GetInt(“PlayerLevel”); It can’t write to an object that isn’t there.

Case in point, when I tested, I added all the scripts to a cube object. So all of them were instantiated when the game started, meaning, you have to have the scripts (or at least one) attached to a GO.

EDIT: I confirmed that the data was writing to the registry on Windows where the data for PlayerPrefs is stored.

I added the experience script to a empty game object though. Or does it need to be something else? The level of frustration this script is causing me :face_with_spiral_eyes::rage: Seriously though ill add a screenshot.

and the full long ass error code:

NullReferenceException: Object reference not set to an instance of an object
SaveManager.Load () (at Assets/Scripts/SaveManager.cs:51)
SaveManager.LoadGame () (at Assets/Scripts/SaveManager.cs:28)
UnityEngine.Events.InvokableCall.Invoke (System.Object[ ] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:153)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[ ] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:634)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[ ] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:769)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()

I know everything should be working and I have gone over everything multiple times but this… this is just annoying. If all else fail mind if I send you the project so you can have a look at the source?

Did you apply the changes to the SaveManager prefab. it shows that you have unapplied changes.

EDIT: Sure, I’d be happy to take a look if needs be. I’ll PM you my email if that time comes. But, what I would say is a little struggle is good but don’t get frustrated. Unity is telling you the problem, the Exp object isn’t getting instantiated. Once you figure out why it isn’t, it’ll start working. Or at the very least, that part won’t be an issue anymore. :wink:

Just checked and apparently PlayerPrefs saves in the registry so i went and had a look but there wasn’t anything saved there so I’m thinking for some reason its not working with my Unity version.

Means it doesnt exists.

Check these lines (51 and 28)
What script is it referencing, make sure it exists.