Search Unity

Saving ScriptableObjects error

Discussion in 'Scripting' started by Pavlos_Mavris, Aug 23, 2020.

  1. Pavlos_Mavris

    Pavlos_Mavris

    Joined:
    Sep 17, 2018
    Posts:
    57
    Hello everyone, I'm trying to save some variables of the ScriptableObject that I created but i'm getting an error during the load() and save() methods. Basically I have 2 boolean variables in every scriptableobjects that defines which one of those was bought and which one is equipped by setting them to true or false

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6.     public class ShopManager : MonoBehaviour
    7.     {
    8.         public static ShopManager instance;
    9.  
    10.         public SpearObject[] spears;                                    //We create an array that contains all the scribtable objects that we created
    11.         public int currentSpear = 0;
    12.         [HideInInspector] public GameObject playerSpear;                //This will be the spear object that the player holds on his hand
    13.         [HideInInspector] public SpriteRenderer spearSprite;            //This will be the spriterenderer component of the spear object that the player holds on his hand
    14.  
    15.         public void Awake()
    16.         {
    17.             instance = this;
    18.             DontDestroyOnLoad(gameObject);           //We don't want this to get destroyed when we change scenes
    19.        
    20.             LoadData();        
    21.         }
    22.  
    23.         // Start is called before the first frame update
    24.         void Start()
    25.         {
    26.            
    27.  
    28.             spearSprite = playerSpear.GetComponent<SpriteRenderer>();                   //We get the sprite renderer component of the object
    29.             spearSprite.sprite = spears[PlayerPrefs.GetInt("currentSkin")].icon;        //We set the sprite of the spear to be equal as the one that is selected through the shop
    30.  
    31.            
    32.         }
    33.  
    34.        
    35.         public void SaveData()
    36.         {
    37.             SaveSystem.SavePlayer(this);
    38.             Debug.Log("Save Data");
    39.         }
    40.  
    41.         public void LoadData()
    42.         {
    43.             GameData data = SaveSystem.LoadData();
    44.  
    45.             for(int i=0;i<=spears.Length;i++)
    46.             {
    47.                 spears[i].bought = data.spear_bought[i];
    48.                 spears[i].equip = data.spear_equip[i];
    49.             }
    50.  
    51.             for (int i = 0; i <= helmets.Length; i++)
    52.             {
    53.                 helmets[i].bought = data.helmet_bought[i];
    54.                 helmets[i].equiped = data.helmet_equip[i];
    55.             }
    56.  
    57.             for (int i = 0; i <= trailColors.Length; i++)
    58.             {
    59.                 trailColors[i].bought = data.trail_bought[i];
    60.                 trailColors[i].equip = data.trail_equip[i];
    61.             }
    62.  
    63.             Debug.Log("Load completed");
    64.         }
    65.  
    66.  
    67.     }
    68.  
    69.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.     [System.Serializable]
    6.     public class GameData
    7.     {
    8.    
    9.         public bool[] spear_bought;
    10.         public bool[] spear_equip;
    11.  
    12.         public bool[] helmet_bought;
    13.         public bool[] helmet_equip;
    14.  
    15.         public bool[] trail_bought;
    16.         public bool[] trail_equip;
    17.  
    18.         public GameData(ShopManager shopmanager)
    19.         {
    20.        
    21.         for (int i = 0; i <= shopmanager.spears.Length; i++)
    22.         {
    23.                 spear_bought[i] = shopmanager.spears[i].bought;
    24.                 spear_equip[i] = shopmanager.spears[i].equip;
    25.                 Debug.Log("Game Data spear");
    26.         }
    27.  
    28.         for (int i = 0; i <= shopmanager.helmets.Length; i++)
    29.         {
    30.             helmet_bought[i] = shopmanager.helmets[i].bought;
    31.             helmet_equip[i] = shopmanager.helmets[i].equiped;
    32.         }
    33.  
    34.         for (int i = 0; i <= shopmanager.trailColors.Length; i++)
    35.         {
    36.             trail_bought[i] = shopmanager.trailColors[i].bought;
    37.             trail_equip[i] = shopmanager.trailColors[i].equip;
    38.         }
    39.        }
    40.     }
    When I try to save the data I'm getting an error at line 23 that says:

    NullReferenceException: Object reference not set to an instance of an object
    GameData..ctor (ShopManager shopmanager) (at Assets/Scripts/SaveSystem/GameData.cs:23)
    SaveSystem.SavePlayer (ShopManager shopmanager) (at Assets/Scripts/SaveSystem/SaveSystem.cs:15)
    ShopManager.SaveData () (at Assets/Scripts/Shop/ShopManager.cs:37)
    UnityEngine.Events.InvokableCall.Invoke () (at <2feaf16e80004e0cadae3f2e05f2a3fa>:0)
    UnityEngine.Events.UnityEvent.Invoke () (at <2feaf16e80004e0cadae3f2e05f2a3fa>:0)
    UnityEngine.UI.Button.Press () (at C:/Program Files/Unity/Hub/Editor/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:68)
    UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/Program Files/Unity/Hub/Editor/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:110)
    UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/Program Files/Unity/Hub/Editor/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:50)
    UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at C:/Program Files/Unity/Hub/Editor/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:261)
    UnityEngine.EventSystems.EventSystem:Update() (at C:/Program Files/Unity/Hub/Editor/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/EventSystem.cs:377)



    Code (CSharp):
    1. using UnityEngine;
    2. using System.IO;
    3. using System.Runtime.Serialization.Formatters.Binary;
    4.  
    5.  
    6.     public static class SaveSystem
    7.     {
    8.  
    9.         public static void SavePlayer(ShopManager shopmanager)
    10.         {
    11.             BinaryFormatter formatter = new BinaryFormatter();
    12.             string path = Application.persistentDataPath + "/shop.troll";
    13.             FileStream stream = new FileStream(path, FileMode.Create);
    14.  
    15.             GameData data = new GameData(shopmanager);
    16.  
    17.             formatter.Serialize(stream, data);
    18.             stream.Close();
    19.         }
    20.        
    21.         public static GameData LoadData()
    22.         {
    23.             string path = Application.persistentDataPath + "/shop.troll";
    24.            
    25.             if (File.Exists(path))
    26.             {
    27.                
    28.                 BinaryFormatter formatter = new BinaryFormatter();
    29.                 FileStream stream = new FileStream(path, FileMode.Open);
    30.                 Debug.Log("path: " + path);
    31.  
    32.                 GameData data = formatter.Deserialize(stream) as GameData;  
    33.                 stream.Close();          
    34.                 return data;          
    35.             }
    36.             else
    37.             {
    38.                 Debug.Log("Save file not found in " + path);              
    39.                 return null;
    40.             }
    41.         }
    42.  
    43.     }
    44.  
    45.  
    When I try to load the data I'm getting an error at line 32 that says:

    "
    SerializationException: Attempting to deserialize an empty stream.
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck, System.Boolean isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage) (at <fb001e01371b4adca20013e0ac763896>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage) (at <fb001e01371b4adca20013e0ac763896>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck) (at <fb001e01371b4adca20013e0ac763896>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) (at <fb001e01371b4adca20013e0ac763896>:0)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) (at <fb001e01371b4adca20013e0ac763896>:0)
    "

    Here is the ScriptableObject asset:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. //This is the scribtable object that we can create
    7. [System.Serializable]
    8. public class SpearObject : ScriptableObject
    9. {
    10.     public string spearName = "Spear name";
    11.     public int cost = 50;
    12.     public string description;
    13.     public bool bought;
    14.     public bool equip;
    15.  
    16.     public Sprite icon;
    17. }


    This method is when the player buys an item:

    Code (CSharp):
    1. //This method will be executed when the player tries to buy an item "spear"
    2.         public void OnClick()
    3.         {
    4.             if(coins >= shopManager.spears[spearNumber].cost)        //If the current total coins are more than the spear cost then the player can buy the item
    5.             {
    6.                 coins -= shopManager.spears[spearNumber].cost;       //We subtracting the cost of the item from the total coins
    7.                 PlayerPrefs.SetInt("coins", coins);                  //We save the new total of coins that the player has
    8.                 //EquipedButton();                                   //The EquipedButton() method will be executed
    9.                 shopManager.spears[spearNumber].bought = true;       //We set the specific variable of the scribtable object to true, and by that we now that the specific item was bought      
    10.                 gameObject.SetActive(false);                         //immediately we disable the buy button        
    11.                 shopManager.SaveData();
    12.                 Debug.Log("Item bought");
    13.  
    14.             }
    15.             else                                                     //If the coins are not enough to buy the item
    16.             {
    17.                 Debug.Log("Not enough coins! " + coins);
    18.  
    19.             }
    20.         }

    I hope all that to make sense because I've been trying to solve this issue for at least 3 days.

    Thank you for your time
     
  2. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Hey there,

    so well you cant Load if the Save function doesnt work,

    to Save it, it needs to run problemless obv.

    it says it have encountered an "NullExceptionError" at line 23.

    Code (CSharp):
    1. spear_bought[i] = shopmanager.spears[i].bought;
    i would say that your "Spears" Array, is not filled up at the position your for loop try to access it,
    that sayd, try to print out, 1 line before, all your spear objects, one by one,

    also,

    Code (CSharp):
    1.         for (int i = 0; i <= shopmanager.spears.Length -1; i++)
    2.         {
    3.                 spear_bought[i] = shopmanager.spears[i].bought;
    4.                 spear_equip[i] = shopmanager.spears[i].equip;
    5.                 Debug.Log("Game Data spear");
    6.         }
    7.  
    could help since you go through an array and the length return 1 more since arrays start at 0,

    another small tipp: Try to store first one, and load one before trying to save and load the whole chunk :)