Trouble saving game data

I’m trying to save game info on exit to be loaded on start.
Such as ammo.

My weapon script sets the values in inspector, then my firetype script inherits from it, and which firetype script is attached to an object
.
I want to save ammo count to be whatever it is at current. Say if starts at 100 and you exit when 60, when you reopen, ammo is 60.

here’s current attempt:

using UnityEngine;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;


public class WeaponStats : MonoBehaviour
{
    public GameObject bullet;
    public Transform Muzzel;

    public int ammunition;
    public int shotValue;
    public float damage;
    public float fireRate;
    public float weaponRange;
    public float bulletVelocity;
    float timer;


    public void OnApplicationQuit()
    {
        BinaryFormatter bf = new BinaryFormatter ();
        FileStream file = File.Create(Application.persistentDataPath + "/PWeapons.dat");

        WeaponData statsData = new WeaponData ();
        statsData.ammunition = ammunition;

        bf.Serialize (file, statsData);
        file.Close();
    }

    public void OnApplicationStart()
    {
        if(File.Exists(Application.persistentDataPath + "/PWeapons.dat"))
        {
            BinaryFormatter bf = new BinaryFormatter ();
            FileStream file = File.Open(Application.persistentDataPath + "/PWeapons.dat", FileMode.Open);
            WeaponData statsData = (WeaponData)bf.Deserialize(file);
            file.Close();

            ammunition = statsData.ammunition;
    }

    }

    [Serializable]
    public class WeaponData
    {
        public int ammunition;
        public int shotValue;
        public float damage;
        public float fireRate;
        public float weaponRange;
        public float bulletVelocity;
    }
}

later on I am going to implement a weapon experience so for now I just want to get it working with ammunition as a waters tester kinda thing.

You say you’re having trouble, but you didn’t say what the trouble was. Is it not creating the file? Not saving the proper value? Not loading the value? What are you running into?

One issue that stands out is that, while OnApplicationQuit certainly exists, there is no corresponding OnApplicationStart method. Try moving that block into an Awake or Start method, instead.

If you make WeaponData a ScriptableObject you can use OnEnable and OnDisable for when to load/Save the data.

For ScriptableObjects:

  • OnEnable will fire when the first object in the scene references it.
  • OnDisable will fire when the last object in the scene dereferences it.

thus when you quit a game OnDisable will fire the moment the last object stops using it, while OnEnable will fire when the game starts up and the first object attempts to use it. which will work great when you quit a game and return later.

When a Scene loads it depends. normally objects will stop using scriptableobjects during scene load since they are getting destroyed. Thus, ScriptableObjects will normally fire OnDisable and OnEnable. However OnDisable+OnEnable will not fire if a script with DontDestroyOnLoad or an object in a scene loading via Async are referencing the ScriptableObject (because at least one object in the scene is still using it).

My problem was it wasn’t saving corresponding ammo data. I have fixed with this:

using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

[Serializable]
public class WeaponStats : MonoBehaviour
{
    public GameObject bullet;
    public Transform Muzzel;

    public int ammunition;
    public int shotValue;
    public float damage;
    public float fireRate;
    public float weaponRange;
    public float bulletVelocity;
    float timer;

    void Awake()
    {
        Load ();

    }
        public void OnGUI()
    {
   
        if (GUI.Button (new Rect (10, 100, 100, 30), "save"))
        {
            Save ();
        }
   

        if (GUI.Button (new Rect (10, 140, 100, 30), "Load")) 
        {
            Load ();
        }
    }


    public void Save()
    {
        BinaryFormatter bf = new BinaryFormatter ();
        FileStream file = File.Create(Application.persistentDataPath + "/PWeapons.dat");

        WeaponData statsData = new WeaponData ();
        statsData.ammunition = ammunition;

        bf.Serialize (file, statsData);
        file.Close();
    }

    public void Load()
    {
        if(File.Exists(Application.persistentDataPath + "/PWeapons.dat"))
        {
            BinaryFormatter bf = new BinaryFormatter ();
            FileStream file = File.Open(Application.persistentDataPath + "/PWeapons.dat", FileMode.Open);
            WeaponData statsData = (WeaponData)bf.Deserialize(file);
            file.Close();

            ammunition = statsData.ammunition;
    }

    } 

    [Serializable]
    public class WeaponData
    {
        public int ammunition;
        public int shotValue;
        public float damage;
        public float fireRate;
        public float weaponRange;
        public float bulletVelocity;
    }
}

and

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

[System.Serializable]
public class Automatic : WeaponStats
{
    GameObject trigger;
    Automatic automatic;
    float timer;


    public void Awake()
    {
        automatic = GetComponent<Automatic> ();
    }


    public void Start()
    {
        PrimaryAmmo.ammo = ammunition;
    }
       
    public void Update ()
    {
        PrimaryAmmo.ammo = ammunition;
       
        timer += Time.deltaTime; 

        if(Input.GetKey(KeyCode.Space)  && timer >= fireRate && Time.timeScale != 0)
        {
            Shoot ();
            ammunition = ammunition - shotValue;

            if (PrimaryAmmo.ammo <= 0) 
            {
                automatic.enabled = false;
                ammunition = 0;
            }
        }
    }
       
    public void DisableEffects ()
        {
        }

    public void Shoot ()
    {
        if (Instantiate (bullet, Muzzel.position, Muzzel.rotation)) 
        {
            PrimaryAmmo.ammo +=  -shotValue;
        }
    }
}