0

I am having an issue where I am only able to store one slider value to playerprefs. I have 10 sliders and if I attach this script, they all inherit the saved value of the first slider in the hierarchy.

public Slider Slider;
public float valueofslider ;


void Start()
{
valueofslider = PlayerPrefs.GetFloat("valueofslider");
Slider.value = valueofslider;
}

void Update()
{

  valueofslider = Slider.value;

if (Input.GetKeyDown(KeyCode.S))
{
    PlayerPrefs.SetFloat("valueofslider", valueofslider);
    Debug.Log("save");
    }
 }

}

Edited code using suggestions to save to Json, but not saving currently. Not sure if the order of operations is correct.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using LitJson;
using System.Text;
using System.Web;
using System;

public class jsonbuttonserialize : MonoBehaviour
{
    [SerializeField]
    public class Sliders
    {
        public float value;
        public float minValue;
        public float maxValue;
        public bool wholeNumbers;

        public string objName;
    }

    [SerializeField]
    public class SliderInfo
    {
        public List<Sliders> sliders;

        public SliderInfo()
        {
            sliders = new List<Sliders>();
        }

        public SliderInfo(Slider[] slider)
        {
            sliders = new List<Sliders>();
            for (int i = 0; i < slider.Length; i++)
                AddSlider(slider[i]);
        }

        public void AddSlider(Slider slider)
        {
            Sliders tempSlider = new Sliders();

            tempSlider.value = slider.value;
            tempSlider.minValue = slider.minValue;
            tempSlider.maxValue = slider.maxValue;
            tempSlider.wholeNumbers = slider.wholeNumbers;

            tempSlider.objName = slider.name;
            sliders.Add(tempSlider);
        }
    }

    public class DataSaver
    {
        //Save Data
        public static void saveData<T>(T dataToSave, string dataFileName)
        {
            string tempPath = Path.Combine(Application.persistentDataPath, "data");
            tempPath = Path.Combine(tempPath, dataFileName + ".txt");

            //Convert To Json then to bytes
            string jsonData = JsonUtility.ToJson(dataToSave, true);
            byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);

            //Create Directory if it does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
            }
            //Debug.Log(path);

            try
            {
                File.WriteAllBytes(tempPath, jsonByte);
                Debug.Log("Saved Data to: " + tempPath.Replace("/", "\\"));
            }
            catch (Exception e)
            {
                Debug.LogWarning("Failed To PlayerInfo Data to: " + tempPath.Replace("/", "\\"));
                Debug.LogWarning("Error: " + e.Message);
            }
        }

        //Load Data
        public static T loadData<T>(string dataFileName)
        {
            string tempPath = Path.Combine(Application.persistentDataPath, "data");
            tempPath = Path.Combine(tempPath, dataFileName + ".txt");

            //Exit if Directory or File does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
            {
                Debug.LogWarning("Directory does not exist");
                return default(T);
            }

            if (!File.Exists(tempPath))
            {
                Debug.Log("File does not exist");
                return default(T);
            }

            //Load saved Json
            byte[] jsonByte = null;
            try
            {
                jsonByte = File.ReadAllBytes(tempPath);
                Debug.Log("Loaded Data from: " + tempPath.Replace("/", "\\"));
            }
            catch (Exception e)
            {
                Debug.LogWarning("Failed To Load Data from: " + tempPath.Replace("/", "\\"));
                Debug.LogWarning("Error: " + e.Message);
            }

            //Convert to json string
            string jsonData = Encoding.ASCII.GetString(jsonByte);

            //Convert to Object
            object resultValue = JsonUtility.FromJson<T>(jsonData);
            return (T)Convert.ChangeType(resultValue, typeof(T));
        }

        public static bool deleteData(string dataFileName)
        {
            bool success = false;

            //Load Data
            string tempPath = Path.Combine(Application.persistentDataPath, "data");
            tempPath = Path.Combine(tempPath, dataFileName + ".txt");

            //Exit if Directory or File does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
            {
                Debug.LogWarning("Directory does not exist");
                return false;
            }

            if (!File.Exists(tempPath))
            {
                Debug.Log("File does not exist");
                return false;
            }

            try
            {
                File.Delete(tempPath);
                Debug.Log("Data deleted from: " + tempPath.Replace("/", "\\"));
                success = true;
            }
            catch (Exception e)
            {
                Debug.LogWarning("Failed To Delete Data: " + e.Message);
            }

            return success;
        }
    }

    public class buttonsave : MonoBehaviour
    {
        SliderInfo loadedSliders;
        Slider[] slider;

        void Start()
        {   
            //Load Slider Settings
            loadedSliders = DataSaver.loadData<SliderInfo>("Sliders");

            //Get current sliders in the Scene
            slider = FindObjectsOfType(typeof(Slider)) as Slider[];

            /*Loop over loadedSliders.sliders then compare the objName with
              slider.name, if they match, assign the value*/
        }

        void Update()
        {
            if (Input.GetKeyDown(KeyCode.S))
            {
                Slider[] slider = FindObjectsOfType(typeof(Slider)) as Slider[];
                SliderInfo sliderInfo = new SliderInfo(slider);
                //Save Sliders
                DataSaver.saveData(sliderInfo, "Sliders");
            }
        }
    }
}

Edited with updated code, saving a file called Sliders.txt but no data is recorded in the file...

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

public class JSONSerialize:MonoBehaviour {
    [SerializeField]
    public class Sliders {
        public float value;
        public float minValue;
        public float maxValue;
        public bool wholeNumbers;
        public string objName;
    }


    SliderInfo loadedSliders;
    Slider[] slider;

    void Start() {
        //Load Slider Settings
        loadedSliders = DataSaver.loadData<SliderInfo>("Sliders");

        //Get current sliders in the Scene
        slider = FindObjectsOfType(typeof(Slider)) as Slider[];


    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.S)) {
            Slider[] slider = FindObjectsOfType(typeof(Slider)) as Slider[];
            SliderInfo sliderInfo = new SliderInfo(slider);
            //Save Sliders
            DataSaver.saveData(sliderInfo,"Sliders");
            Debug.Log("hello");
        }
    }

    [SerializeField]
    public class SliderInfo {
        public List<Sliders> sliders;

        public SliderInfo() {
            sliders = new List<Sliders>();
        }

        public SliderInfo(Slider[] slider) {
            sliders = new List<Sliders>();
            for (int i = 0; i < slider.Length; i++)
                AddSlider(slider[i]);
        }

        public void AddSlider(Slider slider) {
            Sliders tempSlider = new Sliders();

            tempSlider.value = slider.value;
            tempSlider.minValue = slider.minValue;
            tempSlider.maxValue = slider.maxValue;
            tempSlider.wholeNumbers = slider.wholeNumbers;

            tempSlider.objName = slider.name;
            sliders.Add(tempSlider);
        }
    }

    public class DataSaver {
        //Save Data
        public static void saveData<T>(T dataToSave,string dataFileName) {
            string tempPath = Path.Combine(Application.persistentDataPath,"data");
            tempPath = Path.Combine(tempPath,dataFileName + ".txt");

            //Convert To Json then to bytes
            string jsonData = JsonUtility.ToJson(dataToSave,true);
            byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);

            //Create Directory if it does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath))) {
                Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
            }
            //Debug.Log(path);

            try {
                File.WriteAllBytes(tempPath,jsonByte);
                Debug.Log("Saved Data to: " + tempPath.Replace("/","\\"));
            } catch (Exception e) {
                Debug.LogWarning("Failed To PlayerInfo Data to: " + tempPath.Replace("/","\\"));
                Debug.LogWarning("Error: " + e.Message);
            }
        }

        //Load Data
        public static T loadData<T>(string dataFileName) {
            string tempPath = Path.Combine(Application.persistentDataPath,"data");
            tempPath = Path.Combine(tempPath,dataFileName + ".txt");

            //Exit if Directory or File does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath))) {
                Debug.LogWarning("Directory does not exist");
                return default(T);
            }

            if (!File.Exists(tempPath)) {
                Debug.Log("File does not exist");
                return default(T);
            }

            //Load saved Json
            byte[] jsonByte = null;
            try {
                jsonByte = File.ReadAllBytes(tempPath);
                Debug.Log("Loaded Data from: " + tempPath.Replace("/","\\"));
            } catch (Exception e) {
                Debug.LogWarning("Failed To Load Data from: " + tempPath.Replace("/","\\"));
                Debug.LogWarning("Error: " + e.Message);
            }

            //Convert to json string
            string jsonData = Encoding.ASCII.GetString(jsonByte);

            //Convert to Object
            object resultValue = JsonUtility.FromJson<T>(jsonData);
            return (T)Convert.ChangeType(resultValue,typeof(T));
        }

        public static bool deleteData(string dataFileName) {
            bool success = false;

            //Load Data
            string tempPath = Path.Combine(Application.persistentDataPath,"data");
            tempPath = Path.Combine(tempPath,dataFileName + ".txt");

            //Exit if Directory or File does not exist
            if (!Directory.Exists(Path.GetDirectoryName(tempPath))) {
                Debug.LogWarning("Directory does not exist");
                return false;
            }

            if (!File.Exists(tempPath)) {
                Debug.Log("File does not exist");
                return false;
            }

            try {
                File.Delete(tempPath);
                Debug.Log("Data deleted from: " + tempPath.Replace("/","\\"));
                success = true;
            } catch (Exception e) {
                Debug.LogWarning("Failed To Delete Data: " + e.Message);
            }

            return success;
        }

    }
}
LarsTech
  • 80,625
  • 14
  • 153
  • 225
cyo
  • 69
  • 1
  • 14

2 Answers2

1

All the instances of your scripts are changing one key. It's better to do this within one instance of the script. This removes the chances of overwriting an exiting key. Also, since you are saving many sliders, you should step away from using PlayerPrefs and use json and xml then save it as a file manually.

Get the Sliders with FindObjectsOfType(typeof(Slider)) then serialize and save.

It is also important to save the min, max, whole numbers and the name of the Slider so that you can use those information to recreate the slider wen you load it.

For example, Object that holds important slider values:

[SerializeField]
public class Sliders
{
    public float value;
    public float minValue;
    public float maxValue;
    public bool wholeNumbers;

    public string objName;
}

A wrapper that makes it easier to serialize List of Sliders:

[SerializeField]
public class SliderInfo
{
    public List<Sliders> sliders;

    public SliderInfo()
    {
        sliders = new List<Sliders>();
    }

    public SliderInfo(Slider[] slider)
    {
        sliders = new List<Sliders>();
        for (int i = 0; i < slider.Length; i++)
            AddSlider(slider[i]);
    }

    public void AddSlider(Slider slider)
    {
        Sliders tempSlider = new Sliders();

        tempSlider.value = slider.value;
        tempSlider.minValue = slider.minValue;
        tempSlider.maxValue = slider.maxValue;
        tempSlider.wholeNumbers = slider.wholeNumbers;

        tempSlider.objName = slider.name;
        sliders.Add(tempSlider);
    }
}

How to use:

Grab DataSaver class from this post.

Get all sliders:

Slider[] slider = FindObjectsOfType(typeof(Slider)) as Slider[];

Transform into List of Objects ready to be saved:

SliderInfo sliderInfo = new SliderInfo(slider);

Save:

DataSaver.saveData(sliderInfo, "Sliders");

Load:

SliderInfo loadedSliders = DataSaver.loadData<SliderInfo>("Sliders");

You can use the loadedSliders variable to recreate the slider during run-time.

Note:

This should be attached to one GameObject only instead of each Slider in the scene. Empty GameObject is fine.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • This may be a little outside of my range of understanding - if you have time to elaborate on these details I would be enthusiastic to try this method, as I already do see the 10 slider values loading slowly – cyo Mar 26 '18 at 22:03
  • My issue is that I don't know how to composite this code to a working file. I don't understand where to put ``Slider[] slider = FindObjectsOfType(typeof(Slider)) as Slider[]; `` or ``SliderInfo sliderInfo = new SliderInfo(slider);`` or ``DataSaver.saveData(sliderInfo, "Sliders"); `` or ``SliderInfo loadedSliders = DataSaver.loadData("Sliders"); `` – cyo Mar 29 '18 at 15:18
  • You put it where you call the function to save the file. In your other posts it seems like you want to do the saving with a button click so put it in that function the button click will call. The Load part `SliderInfo loadedSliders = DataSaver.loadData("Sliders");` should be in the `Start` function since you want to load it when game begins – Programmer Mar 29 '18 at 15:21
  • thank you, edited my post with new code but still some issues with getting the save function to work. – cyo Mar 29 '18 at 16:14
  • It's saving and loading. You are not currently applying the loaded data to your slider. I've modified your cod and removed non useful stuff and added more code to fix an issue. You still have to apply that loaded data to the slider. See the edit I made and where I said *"/*Loop over loadedSliders.sliders then compare the objName with slider.name, if they match, assign the value*/"*. – Programmer Mar 29 '18 at 16:46
  • Are you refering to function such as a forloop to loop over loadedSliders.sliders? – cyo Mar 29 '18 at 17:28
  • Yes, I am referring to a `for` loop but `for` loop is not a function. Also it would be better to make sure that each Slider has a unique name because you need to compare the names before loading the settings. – Programmer Mar 29 '18 at 21:28
0

You are saving the slider value to the same key resulting in that key is overwritten each time, in your case the value of the first slider in the hierarchy.

The way to solve it is to give each slider an unique PlayerPrefs key.

One quick way to solve it is to change

valueofslider = PlayerPrefs.GetFloat("valueofslider");
PlayerPrefs.SetFloat("valueofslider", valueofslider);

to

valueofslider = PlayerPrefs.GetFloat(gameObject.name + "valueofslider");
PlayerPrefs.SetFloat(gameObject.name + "valueofslider", valueofslider);

using gameObject.name + "valueofslider" to get an unique key. For this to work, each Game Object that the script is attached to needs an unique name in the scene.

This is only one way to solve it, there are many other better ways to solve this.

Johan Lindkvist
  • 1,734
  • 15
  • 24