Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Unity games中将游戏设置保存到文件中而不返回序列化错误?_C#_Unity3d - Fatal编程技术网

C# 如何在Unity games中将游戏设置保存到文件中而不返回序列化错误?

C# 如何在Unity games中将游戏设置保存到文件中而不返回序列化错误?,c#,unity3d,C#,Unity3d,我正在制作一款Android游戏,选项菜单提供了3种不同的设置:背景音乐音量、音效音量和屏幕侧拍摄按钮的位置。还有一个应该保存的高分 我尝试根据某人提供的答案创建脚本,但当我使用音乐音量滑块测试它时,它会不断返回有关无法序列化的内容的错误。起初它说SerializationException:Assembly“Assembly CSharp,Version=0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“GameData”没有标记为可序列化,所以我尝

我正在制作一款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:共享冲突

代码如下:

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,这是我关于斜杠缺失部分的错误。我保留了+并只在第一个字段中写入,而不是使用逗号。