Jump to content
Unity Insider Forum

PlayerPrefs zu JSON - nur wie?


Mauri
 Share

Recommended Posts

Ich möchte weg von PlayerPrefs und hin zu JSON. Dafür hatte ich mir folgendes Tutorial angeschaut:


Soweit auch so gut und relativ verständlich. Nur weiß ich nicht, wie ich es mit meinem bestehenden Script (SceneDataManager.cs) verbinde. Anbei meine aktuellen Scripts.


SceneData.cs
-

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

/// <summary>
/// This class contains all the variables that will be serialized and saved to a file.<br/>
/// Can be considered as a save file structure or format.
/// </summary>
namespace SaveSystem {
	
	[System.Serializable]
	public class SceneData
	{
		public bool IsBloomEnabled;
	}
	
}

-

SaveDataManager.cs
-

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

namespace SaveSystem {

	public static class SaveDataManager
	{
		public static SceneData CurrentSaveData = new SceneData();
		
		public const string SaveDirectory = "/SaveData/";
		public const string FileName = "Settings.json";
		
		public static bool SaveMyData()
		{
			var dir = Application.persistentDataPath + SaveDirectory;
			
			if (!Directory.Exists(dir))
				Directory.CreateDirectory(dir);
			
			string json = JsonUtility.ToJson(CurrentSaveData, true);
			File.WriteAllText(dir + FileName, json);
			
			GUIUtility.systemCopyBuffer = dir + FileName;
			
			return true;
		}
		
		public static void LoadMyData()
		{
			string fullPath = Application.persistentDataPath + SaveDirectory + FileName;
			SceneData tempData = new SceneData();
			
			if (File.Exists(fullPath))
			{
				string json = File.ReadAllText(fullPath);
				tempData = JsonUtility.FromJson<SceneData>(json);
			}
			else
			{
				Debug.LogError("Settings file does not exist!");
			}
			
			CurrentSaveData = tempData;
		}
	}
	
}

_

SceneDataManager.cs
-
[Anmerkung] In meinem Optionsmenü nutze ich Buttons anstatt Toggles, aber das sollte nicht das Problem sein. Man kann das alles sicherlich auch noch eleganter lösen (da gerne Tipps für). Irgendwo ist auch noch ein Fehler drin, aber ich komme nicht darauf...
-

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using TMPro;
using SaveSystem;

[ExecuteInEditMode]
public class SceneDataManager : MonoBehaviour
{
	
	#region Public Properties
	[Header("Universal Render Pipeline Asset")] [Tooltip("Fetch Universal Render Pipeline Asset")]
	[SerializeField] public UniversalRenderPipelineAsset _urpAsset = default;
	
	[Header("Post Processing Volume")] [Tooltip("Fetch PostProcessVolume")]
	[SerializeField] public Volume m_PPVolume;
	[SerializeField] public VolumeProfile m_PPProfile;
	
	[Header("Bloom")]
	[SerializeField] public Bloom m_Bloom;
	[SerializeField] public bool isBloomActive;
	#endregion
	
	#region Buttons & Text
	[Header("Buttons & Text")]
	[SerializeField] public Button m_BloomBtn;
	[SerializeField] public TMP_Text m_BloomTxt;
	#endregion
	
	void Start() {

		m_PPVolume = GameObject.Find("Global Volume").GetComponent<Volume>();
		m_PPVolume.profile.TryGet(out m_Bloom);

		Debug.Log("Found the following PostProcessing Volume: " + m_PPVolume);
		Debug.Log("Found the following PostProcessing Profile: " + m_PPProfile);

		isBloomActive = PlayerPrefs.GetString("BloomSetting") == "on" ? true : false;
		m_BloomBtn.onClick.AddListener(ProcessBloom);
		ProcessBloom();

	}
	
	void ProcessBloom() {
		
		isBloomActive = !isBloomActive;
		PlayerPrefs.SetString("BloomSetting", isBloomActive ? "on" : "off");
		m_BloomTxt.text = isBloomActive ? "On" : "Off";
          
		if ( isBloomActive ) {
			m_Bloom.intensity.value = 1.0f;
			m_BloomTxt.text = "On";
			Debug.Log("Bloom is on");
		}
		else {
			m_Bloom.intensity.value = 0.0f;
			m_BloomTxt.text = "Off";
			Debug.Log("Bloom is off");
		}

	}

}

-

 

Link to comment
Share on other sites

Ich habe mir jetzt das Tutorial nicht angeschaut und jetzt auch nicht genau geschaut, was du so machst, aber ich kann dir sagen wie ich es mache.

In der Klasse (in dem Script) wo das JSONUtility ausgeführt wird, müssen public Variablen liegen, die die Werte, die gespeichert werden sollen, beinhalten.
Der Variablenname wird zum Schlüsselname im JSON File und der Wert der Variable wird dann zum Wert im JSON.
Warum diese Variablen public sein müssen, weiss ich nicht, aber ohne macht er es nicht.
Es sollte auch so gehen, wie du es versuchst, die Daten von wo anders zu holen, aber da hatte ich auch Schwierigkeiten.

Ich sammle meine Daten auch in einem anderen Script und muss die Daten dann ins LoadAndSave Script rüberholen um die Werte zu speichern.
Genau so muss ich beim Laden der Werte, diese dann in mein anderes Script übergeben.
Ich nutze StreamReader und StreamWriter um den JSON String abzuspeicher und zu laden.
Die JSON Funktionen die ich nutze sind:  .toJson()  und  .fromJsonOverwrite()

So mache ich das:
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
public class LoadAndSaveGame : MonoBehaviour{
  StreamReader str; // der Reader fürs Einlesen
  string inhalt; // der erzeugte String zur Übergabe an JSON
  StreamWriter stw; // der Writer fürs Speichern
  
  public int score; // irgend eine Variable
  // weitere Variablen
  //...
  
  public void SaveGame(string saveName){
    
    string line = GenerateString(); // siehe unten
    //schreiben
    stw = new StreamWriter(Application.persistentDataPath + "/" + saveName + ".txt");
    stw.WriteLine(line);
    stw.Flush();
    stw.Close();
  }
  
  public void LoadGame(string saveName){
    // lesen
    str = new StreamReader(Application.persistentDataPath + "/" + saveName + ".txt");
    inhalt = str.ReadLine();
    MindUebergabe(inhalt); // siehe unten
    str.Close();
  }
  
  public string GenerateString(){
    score = mind.score; // Wert aus dem mind Script holen und meiner Variable übergeben
    // hier kämen dann weiter Variablen dran
    
    return JsonUtility.ToJson(this); // string wurde gebildet und wird zurück gegeben
  }
  
  public void MindUebergabe(string savedData){
    JsonUtility.FromJsonOverwrite(savedData, this); // JSON holt sich die Werte aus dem String und setzt sie in die Variablen.
    
    mind.score = score; // Wert ins mind Script schreiben
    // ...
  }
}

Natürlich ist das doppelte Ablegen der Daten eigentlich blöd und ich hätte auch gleich die Variablen im LoadAndSave Script nutzen können.
 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...