unity3d 尝试将总硬币变量保存在随机设备位置Unity2D中

ccrfmcuu  于 2023-02-09  发布在  其他
关注(0)|答案(1)|浏览(132)

因此,我有一个无限的platformer亚军游戏,我保持总的旅行距离和总收集硬币的游戏过程中的价值观.从this视频,我的男孩Brackeys教如何保存和加载关键数据格式的数据使用二进制格式.我用他的代码来创建我自己的高分保存系统.我可以保存最高旅行距离.检查以上代码:
HighScoreData.cs

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

[System.Serializable]
public class HighScoreData
{
    public float bestDistanceCount;

    public HighScoreData(Player player){
        bestDistanceCount = player.distanceCount;
    }
}

HighScoreSaveSystem.cs

using UnityEngine;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public static class HighScoreSaveSystem
{
    public static void SaveHighScore(Player player){
        BinaryFormatter formatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/highscore.highscorefile";
        FileStream stream = new FileStream(path,FileMode.Create);

        HighScoreData data = new HighScoreData(player);
        formatter.Serialize(stream,data);
        stream.Close();
    }
    public static HighScoreData LoadHighScore(){
        string path = Application.persistentDataPath + "/highscore.highscorefile";
        if(File.Exists(path)){
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = new FileStream(path,FileMode.Open);
            HighScoreData data = formatter.Deserialize(stream) as HighScoreData;
            stream.Close();
            return data;
        }
        else{
            Debug.LogError("Save file not found!");
            return null;
        }
    }
}

通过在每次我的玩家死亡时调用KillPlayer()方法,

public void KillPlayer(){
        isDead = true;
        HighScoreData data = HighScoreSaveSystem.LoadHighScore();
        if(distanceCount > data.bestDistanceCount){
            HighScoreSaveSystem.SaveHighScore(this);
        }
        Time.timeScale = 0f;
    }

这个方法很好用,但是要存硬币的话,我就想不出来了。
我必须在这个二进制文件中创建一个变量,当玩家安装游戏时,这个变量将取0。每次玩家死亡时,在那个级别收集的硬币应该添加到我保存在二进制文件中的硬币中。但我不知道如何实现它。
"我尝试了什么"
我尝试添加totalCoins变量到HighScoreData. cs:
HighScoreData.cs

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

[System.Serializable]
public class HighScoreData
{
    public float bestDistanceCount;
    public int totalCoins;

    public HighScoreData(Player player){
        bestDistanceCount = player.distanceCount;
        totalCoins += player.coinCount;
    }
}

在我的KillPlayer()方法中,我尝试将totalCoins数据存储在一个临时变量中,将当前硬币计数添加到该临时变量中,并使用该临时变量更新data.totalCoins,该临时变量名为totalCoinRef

public void KillPlayer(){
        isDead = true;
        HighScoreData data = HighScoreSaveSystem.LoadHighScore();
        int totalCoinRef = data.totalCoins;
        if(distanceCount > data.bestDistanceCount){
            totalCoinRef += coinCount;
            data.totalCoins = totalCoinRef;
            HighScoreSaveSystem.SaveHighScore(this);
        }
        totalCoinRef += coinCount;
        data.totalCoins = totalCoinRef;
        HighScoreSaveSystem.SaveHighScore(this);
        Time.timeScale = 0f;
    }
    • 结果:**

这个解决方案只保留每关收集的硬币数量。它不保留总硬币的总和。例如,如果我收集了5个硬币,数据。TotalCoins将返回5。如果我收集了6个硬币,数据。TotalCoins将返回6。我需要它返回11。
我希望这已经很清楚了。谢谢你抽出时间。

ruarlubt

ruarlubt1#

一般情况下STOP USING BinaryFormatter !
使用其他格式,例如(JSON、原始文本文件等)或自定义二进制序列化。
那么在SaveHighScore

HighScoreData data = new HighScoreData(player);

完全忽略任何先前存在的数据!
你似乎相信

int totalCoinRef = data.totalCoins;

创建一个引用,因此编辑totalCoinRef也将自动编辑data.totalCoins..它不会intValue Type,因此您创建了一个值的副本,该值与data完全无关!
我总是宁愿直接传入一个HighScoreData并执行(现在将简单地使用JSON进行演示)

[System.Serializable]
public class HighScoreData
{
    public float bestDistanceCount;
    public int totalCoins;
}

以及

private static readonly string path = Path.Combine(Application.persistentDataPath, "highscore.highscorefile");

public static void SaveHighScore(HighScoreData data)
{  
    var json = JsonUtility.ToJson(data, true);  
    
    File.WriteAllText(path, json);
}

public static HighScoreData LoadHighScore()
{       
    if(!File.Exists(path)) return new HighScoreData();

    var json = File.ReadAllText(path);
      
    return JsonUtility.FromJson<HighScoreData>(json);
}

最后在播放器中

public void KillPlayer()
{
    isDead = true;

    var data = HighScoreSaveSystem.LoadHighScore();

    data.totalCoins += coinCount;
    data.bestDistanceCount = Mathf.Max(data.bestDistanceCount, distanceCount);    
    
    HighScoreSaveSystem.SaveHighScore(data);
    
    Time.timeScale = 0f;
}

如果您希望保持二进制,还可以研究BinaryWriterBinaryReader..在您的情况下,JSON可能有点过头,因为您实际上只需要8字节.. float bestDistanceCount为4,int totalCoins为4。JSON当然会增加相当多的开销,字符串解析总是比简单的字节转换更昂贵
可能看起来像例如。

public static void SaveHighScore(HighScoreData data)
{  
    using(var stream = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)
    {
        using(var writer = new BinaryWriter(stream))
        {
            writer.Write(data.bestDistanceCount);
            writer.Write(data.totalCoins);      
        }    
    }       
}

public static HighScoreData LoadHighScore()
{ 
    var data = new HighScoreData();      
    if(File.Exists(path))
    {
        using(var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)
        {
            using(var reader = new BinaryReader(stream))
            {           
                data.bestDistanceCount = reader.ReadSingle();
                data.totalCoins = reader.ReadInt32();      
            }    
        }  
    }     
      
    return data;
}

无论哪种方式(甚至--也许特别是--使用BinaryFormatter),都要记住用户对持久数据有完全的访问权,可以修改它们的值,你可以使用一些加密来使它更难..但是为了完全防止欺骗,你需要一个服务器解决方案;)

相关问题