C# 如何在Unity games中将游戏设置保存到文件中而不返回序列化错误?
我正在制作一款Android游戏,选项菜单提供了3种不同的设置:背景音乐音量、音效音量和屏幕侧拍摄按钮的位置。还有一个应该保存的高分 我尝试根据某人提供的答案创建脚本,但当我使用音乐音量滑块测试它时,它会不断返回有关无法序列化的内容的错误。起初它说SerializationException:Assembly“Assembly CSharp,Version=0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“GameData”没有标记为可序列化,所以我尝试在类代码上方添加[System.serializable],如建议的那样,但现在它返回错误SerializationException:程序集“UnityEngine.CoreModule,版本=0.0.0.0,区域性=中性,PublicKeyToken=null”中的类型“UnityEngine.MonoBehavior”未标记为可序列化 此外,在序列化错误之后,它还会在路径C:\Users\UserName\AppData\LocalLow\CompanyName\AppName\save.dat上写入错误IOException:共享冲突 代码如下:C# 如何在Unity games中将游戏设置保存到文件中而不返回序列化错误?,c#,unity3d,C#,Unity3d,我正在制作一款Android游戏,选项菜单提供了3种不同的设置:背景音乐音量、音效音量和屏幕侧拍摄按钮的位置。还有一个应该保存的高分 我尝试根据某人提供的答案创建脚本,但当我使用音乐音量滑块测试它时,它会不断返回有关无法序列化的内容的错误。起初它说SerializationException:Assembly“Assembly CSharp,Version=0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“GameData”没有标记为可序列化,所以我尝
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;
}
}
代码中有什么错误?提前感谢。由于您的GameData类继承自Unity的MonoBehavior,因此序列化要求MonoBehavior也可序列化;但事实似乎并非如此
也许这会有所帮助:MonoBehavior可能不会使用new关键字实例化,这是反序列化程序所必需的。您不需要额外的AddComponent和GetComponent,因为此脚本已经是您要在游戏对象上使用的组件
您至少应该知道,我会将可序列化类型仅分离为纯数据类/-struct,并在实现逻辑的MonoBehavior中使用它的实例
可能看起来像
[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);
}
}
}
似乎启动方法和将脚本附加到UI按钮字段的Unity游戏对象拖动到UI按钮字段的能力都需要单行为。我会看看你提供的链接。谢谢!事实上,有人已经在Unity论坛上建议将其分为数据类和处理程序类,我认为这两个类现在都可以工作,即使使用了/也不需要进一步更改,所以我不确定为什么它很重要,但是,您提供了一些进一步的调整,可以使其更好地工作。如果您使用Unity并可能使用不同的操作系统构建到不同的目标平台,则+/是非常危险的,例如/在Unix上vs \或:\for Windows上的驱动器路径。。。只需根据代码运行的操作系统插入正确的路径分隔符!很高兴知道。虽然您似乎无法使用MonoBehavior构造函数中的persistentDataPath,但它告诉我将其置于Start或WAKE,然后它也不需要是只读的。编辑:在使用你的方法时,它似乎没有添加任何斜杠。它将文件保存为公司文件夹中的Appnamesave.dat,而不是CompanyName/AppName/save.datOops,这是我关于斜杠缺失部分的错误。我保留了+并只在第一个字段中写入,而不是使用逗号。