我想使用DontDestroyOnLoad
对象在2D游戏进行时保存游戏数据。
我有一个GameData
类/脚本,用于存储诸如health,magicType等值;一个SaveLoad
类/脚本,用于将GameData类中的当前值保存到Json;还有一个空游戏对象,称为{ {1}}具有以上两个脚本。
当前,我通过使用按钮单击事件将值保存在一个场景中。我附加到按钮上的对象是PlayerData
对象,我在点击事件上使用PlayerData
脚本更改了值。
但这仅适用于第一个场景-我无法附加GameData
对象并存储其PlayerData
值,因为编辑器中没有PlayerData对象。
那么我该如何附加另一个场景中的对象呢?还是我做错了?
这是我当前项目的照片。
另外,当我保存一个布尔值,然后打开我的Json文件时,该文件为空。这正常吗?这是我的保存和加载代码:
加载:
GameData
保存:
private string _filePath;
private static DataService _instance;
public DataService Instance
{
get { return _instance; }
}
public GameData _gameData;
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void LoadGameData()
{
_filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
string json;
if (File.Exists(_filePath))
{
json = File.ReadAllText(_filePath);
JsonUtility.FromJsonOverwrite(json, _gameData);
}
else
{
Debug.Log("File missing.");
}
}
编辑:这是我的GameData类的代码:
public void SaveGameData1()
{
string json = JsonUtility.ToJson(_gameData);
_filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
if (File.Exists(_filePath))
{
File.Create(_filePath).Dispose();
}
File.WriteAllText(_filePath,json);
}
答案 0 :(得分:1)
首先,正如最近回答的here,我不会使用persistentDataPath
进行开发,而是使用streamingAssetsPath
并在首次运行应用程序时将文件复制过来。
我看到您具有Singleton模式的前半部但是:您从未为instance
分配任何值。我通常会在媒体资源或Awake
中将其“懒惰”,例如
private static DataService instance;
public static DataService Instance
{
if(instance) return instance;
instance = FindObjectOfType<DataService>();
if(instance) return instance;
// If it wasnt found in the scene create it now
instance = new GameObject("DataService", typeof (GameData)). AddComponent<DataService>();
instance._gameData = instance.GetComponent<GameData>();
DontDestroyOnLoad (instance.gameObject);
return instance;
}
private void Awake ()
{
if(instance && instance != this)
{
Debug.LogWarning("Another instance of DataService I already in use");
Destroy(gameObject);
return;
}
if(instance) return;
instance = this;
DontDestroyOnLoad (gameObject);
if(!_gameData) _gameData = GetComponent<GameData>();
}
实际上,使用您提供的代码,我怀疑您的两个类中的任何一个是否真的都必须是MonoBehaviour
!
您可能只需使用类似的内容
public static class DataService
{
private const string FILE_NAME = "GameData1.json";
public static GameData GameData = new GameData();
public static void SaveGameData1()
{
var json = JsonUtility.ToJson(_gameData);
var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);
if (File.Exists(filePath))
{
File.Create(filePath);
}
File.WriteAllText(filePath,json);
}
public static void LoadGameData()
{
var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);
if (File.Exists(filePath))
{
var json = File.ReadAllText(_filePath);
JsonUtility.FromJsonOverwrite(json, GameData);
}
else
{
Debug.Log("File missing.");
}
}
}
和
[Serializable]
public class GameData
{
public float SomeValue;
...
}
现在,您可以随处拨打电话
DataService.LoadGameData();
然后访问值,如
DataService.GameData.SomeValue = ...;
我将创建一个类DataServiceButton
,该类将附加到UI.Button上,并像{p>一样注册为onClick
的侦听器
[RequireComponent(typeof(UI.Button))]
public class DataServiceButton : MonoBehaviour
{
public enum ButtonType
{
Save,
Load
}
// This is set via the Inspector
[SerializeField] private ButtonType type;
// Here you can already reference the according Button component
[SerializeField] private Button button;
private void Awake()
{
if(!button) button = GetComponent<Button>();
// Register as callback
button.onClick.AddListener(HandleClick);
}
private void HandleClick()
{
switch(type)
{
case ButtonType.Load:
DataService.LoadGameData();
// OR IF YOU STICK TO THE SINGLETON
//DataService.Instance.LoadGameData();
break;
case ButtonType.Save:
DataService.SaveGameData();
// OR ACCORDINGLY WITH SINGLETON
//DataService.Instance.SaveGameData();
break;
}
}
}
不幸的是,为什么写数据后文件为空的问题在没有看到您的GameData
类的代码的情况下无法回答...
确保您的类型可序列化。