我正在制作一款安卓游戏,选项菜单提供了3个不同的设置:背景音乐音量、音效音量、屏幕侧射击按钮的位置。还有高分应该保存。
我试着根据某人提供的答案创建了一个脚本,但当我用音乐音量滑块测试时,它一直在返回关于事物不可序列化的错误。一开始它说 "SerializationException: Type 'GameData' in Assembly 'Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable",所以我试着按照某个地方的建议在类代码上方添加"[System.Serializable]",但现在它却返回错误 "SerializationException: Type 'UnityEngine.MonoBehaviour' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable"。
另外,在序列化错误之后,它还写了错误 "IOException: 路径C:\Users\UserName\AppData\LocalLow\CompanyName\AppName\save.dat上存在共享违规"。
这是代码。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
[System.Serializable]
public class GameData : MonoBehaviour
{
public int highScore = 0;
public float musicVol = 1;
public float sfxVol = 1;
public int shootSide = 1;
// Start is called before the first frame update
private void Start()
{
LoadFile();
}
public void HighScoreValue(int highS)
{
highScore = highS;
SaveData();
}
public void MusicValue(float musicV)
{
musicVol = musicV;
SaveData();
}
public void SfxValue(float sfxV)
{
sfxVol = sfxV;
SaveData();
}
public void ShootSideValue(int shootS)
{
shootSide = shootS;
SaveData();
}
private void SaveData()
{
string destination = Application.persistentDataPath + "/save.dat";
FileStream file;
if (File.Exists(destination))
{
file = File.OpenWrite(destination);
}
else
{
file = File.Create(destination);
}
GameData data = gameObject.AddComponent<GameData>();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(file, data);
file.Close();
}
private void LoadFile()
{
string destination = Application.persistentDataPath + "/save.dat";
FileStream file;
if (File.Exists(destination))
{
file = File.OpenRead(destination);
}
else
{
Debug.Log("File not found");
return;
}
BinaryFormatter formatter = new BinaryFormatter();
GameData data = (GameData)formatter.Deserialize(file);
file.Close();
highScore = data.highScore;
musicVol = data.musicVol;
sfxVol = data.sfxVol;
shootSide = data.shootSide;
}
}
代码中有什么问题?先谢谢你了。
MonoBehaviour
可能无法实例化使用 new
关键字,这是解串器所需要的。您的附加 AddComponent
和 GetComponent
不需要,因为这个脚本已经 是 的组件,您想在 GameObject
.
你应该(至少我会)将可序列化类型分离成一个纯数据类结构,并在实现逻辑的MonoBehaviour中使用它的一个实例。
可以像这样
[Serializable]
public class GameDataContainer
{
public int highScore = 0;
public float musicVol = 1;
public float sfxVol = 1;
public int shootSide = 1;
}
public class GameData : MonoBehaviour
{
// since this is a serialized,
// it will be initialized with a valid instance by default
public GameDataContainer data;
// NEVER use +"/" for system paths!
// initilaize this only once
private string destination => Path.Combine(Application.persistentDataPath, "save.dat");
// Start is called before the first frame update
private void Start()
{
LoadFile();
}
public void HighScoreValue(int highS)
{
data.highScore = highS;
SaveData();
}
public void MusicValue(float musicV)
{
data.musicVol = musicV;
SaveData();
}
public void SfxValue(float sfxV)
{
data.sfxVol = sfxV;
SaveData();
}
public void ShootSideValue(int shootS)
{
data.shootSide = shootS;
SaveData();
}
private void SaveData()
{
using (var file = File.Open(destination, FileMode.Create, FileAccess.Write, FileShare.Write))
{
var formatter = new BinaryFormatter();
formatter.Serialize(file, data);
}
}
private void LoadFile()
{
if (!File.Exists(destination))
{
Debug.Log("File not found");
return;
}
using(var file = File.Open(destination, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var formatter = new BinaryFormatter();
data = (GameDataContainer)formatter.Deserialize(file);
}
}
}
由于你的 GameData
类继承自Unity的 MonoBehaviour
,序列化将需要 MonoBehaviour
也是可序列化的;但似乎不是。
也许这将会有所帮助。序列化&反序列化Unity3D MonoBehaviour脚本。