【问题标题】:Unity 3D 2018.1 - Save [duplicate]Unity 3D 2018.1-保存[重复]
【发布时间】:2018-05-20 10:36:02
【问题描述】:

我一周前开始做一个简单的构建游戏,现在我想要一个“保存系统”。问题是,到目前为止,无论我尝试过什么,我都做不到。具体来说,我不知道它是否会起作用,因为它必须存储 100x100 大小的地面,以及树木、石头和建筑。 游戏在每次运行开始时随机生成世界。

知道我能做什么吗?

【问题讨论】:

  • 不确定“我不知道它是否会起作用”是什么意思。你的意思是你担心保存太多? 100x100 块,即使每个块使用 100 字节,也小于 1 MiB。
  • 我的意思是,当我开始游戏时,Unity 崩溃了,当我尝试一个技巧(构建游戏并运行)时,游戏也崩溃了。所以我想我需要另一种方法来保存超过 10.000 个瓷砖,外加环境。

标签: c# unity3d save system


【解决方案1】:

PlayerPrefs 和 json 序列化将成为您相对简单的保存系统的朋友。但为了做到这一点,您需要确保您只使用受支持的 PlayerPrefs 类型:int、float 或 string。这并没有提供很大的回旋余地,因此利用这些的最佳方法是使用 json,因为 json 表示为字符串。有关如何使用 Unity 内置的 json 序列化程序,请阅读 here

您对这种设置有何期待?好吧,让我们进行以下设置:

using System;
using UnityEngine;

[Serializable]
public class PlayerStats
{
    public int Health;
    public int Energy;
    public Vector3 Position;

    public static string Serialize(PlayerStats playerStats)
    {
        if (playerStats == null)
            return "";

        return JsonUtility.ToJson(playerStats);
    }

    public static PlayerStats Deserialize(string json)
    {
        if (string.IsNullOrEmpty(json))
            return new PlayerStats();

        return JsonUtility.FromJson<PlayerStats>(json);
    }
}

public static class GameManager
{
    public const string PLAYER_STATS_SAVE_KEY = "PLAYER_STATS";

    public static PlayerStats Player;

    public static void Save()
    {
        string json = PlayerStats.Serialize(Player);
        PlayerPrefs.SetString(PLAYER_STATS_SAVE_KEY, json);
    }

    public static void Load()
    {
        if (!PlayerPrefs.HasKey(PLAYER_STATS_SAVE_KEY))
        {
            Player = new PlayerStats();
        }
        else
        {
            string json = PlayerPrefs.GetString(PLAYER_STATS_SAVE_KEY);
            Player = PlayerStats.Deserialize(json);
        }
    }
}

这里有 2 个类 - PlayerStats 和 GameManager。 PlayerStats 将充当您要序列化(以及稍后保存和加载)的数据的容器。所以你把[Serializable] 属性放在它上面。为您要保存的数据添加字段:健康、能量和位置。然后创建一些静态方法,用于将 PlayerStats 实例序列化和反序列化为 Json 字符串。当我们在类上运行Serialize() 方法时,我们可能会得到一个如下所示的字符串:

{
  "Health": 10,
  "Energy": 10,
  "Position": {
    "x": 1,
    "y": 1,
    "z": 1
  }
}

这意味着我们现在可以将它保存在 PlayerPrefs 中,因为我们已经将所有数据转换为字符串。这就是 GameManager 类的用武之地。假设您将 PlayerStats 存储在该类的静态字段中。当玩家点击保存按钮时,您只需运行GameManager.Save(),它会使用PlayerStats.Serialize() 方法获取当前PlayerStats 的json。然后使用 PlayerPrefs,它将该字符串存储在特定键中。下次您想加载这些玩家统计信息时,您只需调用 GameManager.Load(),它就会从 PlayerPrefs 中检索保存的 json,将其反序列化为 PlayerStats 实例并将其分配给您的全局 PlayerStats 字段。

至于您的世界生成,我强烈建议您切换到种子随机生成器。这将允许您生成一个随机种子,该种子可以保存并可靠地用于重新生成相同的随机数据。这可以通过System.Random(int32) (docs here) 类来完成。因此,您只需保存种子并使用它来重新生成世界,而不是保存所有世界数据。

【讨论】:

  • 谢谢!我试过了,但是当它尝试加载超过 10.000 个游戏对象和组件时,Unity 崩溃了.. :/
  • 哈,你可能需要把它放在一个协程中:每帧生成一个最大数量 -> yield return null -> 循环遍历下一个对象池,直到你已经加载了它们。你可以在这个协程运行时抛出一个加载屏幕(或者不要让用户看到一切慢慢产生我的世界风格)。另外,如果这回答了您的问题,您介意将其标记为完整吗?
猜你喜欢
  • 2017-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2019-01-25
  • 2018-04-11
相关资源
最近更新 更多