Search code examples
c#unity-game-enginescriptable-object

unity Scriptable object not working in bulid


hi I am new to unity and C# and I am making my first game. In it I have a Scriptable object named "sss".It contains values like coins,speed,jump power. It works fine in the editor but after I build it it wont work.what I mean by it wont work is after the player dies in the game depending on how long they live they will get a certain amount of coins when they go to the store they will see those coins displayed as a UI and they can spend them on things like speed and jump boost. this works in the editor but not in a build. Dose anybody know why this is? here is the code I have in my Scriptable object

using UnityEngine;

[CreateAssetMenu(fileName = "data",menuName = "sss",order = 1)]
public class sss : ScriptableObject
{
   public float coins = 0f;
   public float speed = 10f;
   public float jump = -9.81f;
   public bool set = true;
   public int face = 1;

}

here is the code I use to display the coins float

coinstext.text = sss.coins.ToString();

and here is the whole store-manager script used to buy stuff

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Security;
using UnityEngine;
using UnityEngine.UI;

public class storemanager : MonoBehaviour
{
    public sss sss;
    public Text coinstext;
    public Slider sliders;
    public Slider sliderj;
    public int maxcap = 30;
    public int maxcapj = 500;
    public void Start()
    {


    coinstext.text = sss.coins.ToString();

    }

public void speedbuy()
{


    if (sss.coins >= 5 && sss.speed < maxcap)
    {
        sss.speed += 1;
        sss.buyspeed = true;
        sss.coins -= 5;
        sliders.value += 1;
        coinstext.text = sss.coins.ToString();
    }
}

public void jumpbuy()
{


    if (sss.coins >= 7 && sss.jump < maxcapj)
    {
        sss.jump += 10;
        sss.buyjump = true;
        sss.coins -= 7;
        sliderj.value += 10;
        coinstext.text = sss.coins.ToString();

    }
}
}

Solution

  • While changes in ScriptableObject within the UnityEditor are persistent, they are not persistent in a build!

    When you use the Editor, you can save data to ScriptableObjects while editing and at run time because ScriptableObjects use the Editor namespace and Editor scripting. In a deployed build, however, you can’t use ScriptableObjects to save data, but you can use the saved data from the ScriptableObject Assets that you set up during development.

    So after a build the data in the asset is kind of baked and you can change it at runtime but when restarting the app you will always re-load the data of the build.


    You would need to store your data instead in a local file stored on the device itself e.g. using Json like

    using UnityEngine;
    using System.IO;
    ...
    
    public class sss : ScriptableObject
    {
        public float coins = 0f;
        public float speed = 10f;
        public float jump = -9.81f;
        public bool set = true;
        public int face = 1;
    
        private const string FILENAME = "sss.dat";
    
        public void SaveToFile()
        {
            var filePath = Path.Combine(Application.persistentDataPath, FILENAME);
    
            if(!File.Exists(filePath))
            {
                File.Create(filePath);
            }
           
            var json = JsonUtility.ToJson(this);
            File.WriteAllText(filePath, json);
        }
            
    
        public void LoadDataFromFile()
        {
            var filePath = Path.Combine(Application.persistentDataPath, FILENAME);
    
            if(!File.Exists(filePath))
            {
                Debug.LogWarning($"File \"{filePath}\" not found!", this);
                return;
            }
    
            var json = File.ReadAllText(filePath);
            JsonUtility.FromJsonOverwrite(json, this);
        }
    }
    

    And then in your manager script call the load and save methods e.g.

    public class storemanager : MonoBehaviour
    {
        public sss sss;
    
        public Text coinstext;
        public Slider sliders;
        public Slider sliderj;
        public int maxcap = 30;
        public int maxcapj = 500;
    
        public void Start()
        {
            sss.LoadFromFile();
    
            coinstext.text = sss.coins.ToString();
        }
    
        // Called when the application is going to quit
        private void OnApplicationQuit()
        {
            sss.SaveToFile();
        }
    

    Note: Typed on smartphone but I hope the idea gets clear