【问题标题】:Save and Load the state of gameobjects in a scene in Unity在 Unity 中保存和加载场景中游戏对象的状态
【发布时间】:2016-04-14 08:42:47
【问题描述】:

所以我想要完成的是,当我加载场景时,我希望某些对象处于活动或非活动状态,具体取决于它们保存在我的文件中的信息。

例如:

在我的游戏中,当我加载我的一个场景时,有一堵墙,然后我将书柜推到某个点并触发墙设置为非活动状态。我退出这个场景,然后回到场景中,墙又是活跃的。我想要的是当墙被设置为非活动状态时,即使我离开场景它也保持非活动状态,并且当我稍后回到场景时不会出现。

我遇到的麻烦是如何做到这一点。目前我所拥有的是当玩家单击“新游戏”按钮时,我会生成一个新的 Game_Info 并选择 Default() :

[Serializable]
public class Game_Info {

    public bool WoodWallEnabled;

    public void Default(){
        WoodWallEnabled = true;
    }
}

我的 WoodWall 脚本:

public class Get_WoodWall_Info : MonoBehaviour {

    void Awake () {
        gameObject.SetActive (Helper_Manager.instance.gameInfo.WoodWallEnabled);
    }
}

我有一种感觉,我没有以正确的方式执行此操作,并且有更好的方法来处理此问题,特别是因为这样做需要为每个我想通过我保存的文件操作的游戏对象创建一个唯一的脚本( Get_WoodWall_Info、Get_WoodWall_Info1 等...),但即使我创建了大量脚本来执行此操作,我也找不到保存游戏对象状态的方法。

您将如何处理和传递此类数据?

【问题讨论】:

  • 我为您问题的另一部分编辑了我的答案。我很抱歉之前没有注意到那部分。无论如何,希望对您有所帮助。

标签: unity3d


【解决方案1】:

如果您只保存WoodWallEnabled 变量,那么如上所述简单地使用PlayerPref。现在,如果您要保存整个场景信息,例如对象位置或Game_Info 类中的每个变量,您必须使用JsonUtility.ToJsonclass 转换为 Json,然后使用PlayerPref保存它。然后加载它,您使用PlayerPref 加载它,然后使用JsonUtility.FromJson 将其序列化回您的Game_Info 类。

包含数组的完整工作示例:

Serialize and Deserialize Json and Json Array in Unity

【讨论】:

  • 是的,我将在场景中保存重要信息,但不是全部。就像我提到移动书柜时,我在那个场景中有大约 5 个书柜,但我只关心其中 1 个的位置作为示例。有些场景需要保存的内容很少,而有些场景需要保存的内容更多。
  • 我在上面发布的链接中的解决方案应该适合你。
  • 谢谢程序员 我去看看。顺便问一下,使用这种方法的安全性如何?我记得看过一个 Unity 教程,说使用 PlayerPrefs 并不安全,因为用户可以直接进入并将文件编辑为他们想要的。
  • 您的帖子没有提及任何有关安全的内容。您应该担心人们在本地玩您的游戏。您唯一需要担心的是当两个玩家在线玩时,您应该实施一些作弊预防机制。在线游戏与本地分数无关,所以不用担心。
  • 现在,如果您仍想花时间阻止玩家更改分数,那么请了解加密。您可以在使用PlayerPref 保存之前对其进行加密。加密字符串的方法有很多种,但我相信您可以在谷歌 C# 字符串加密时找到很多方法。 MD5 和更多。如果链接中的这个解决方案对你有用,那么你可以接受这个作为答案。
【解决方案2】:

我认为PlayerPref 在这种情况下是一个不错的选择。 你可以这样做:

  • 调用PlayerPrefs.SetInt("wall enabled", active ? -1 : 0); 保存木墙的状态,active 是墙的状态。

  • Get_WoodWall_Info 中,不要使用帮助管理器中的值,而是使用 PlayerPrefs.GetInt("wall enabled") != 0

PlayerPrefs 中的值将通过游戏会话保存,因此您可能希望在开始新游戏时将 wall enabled 键设置为 0。

编辑

@JoeyL 为什么不为所有游戏对象创建一个脚本,如下所示:

public class StateHandler : MonoBehaviour {
    void Awake () {
        string keyName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + gameObject.name;
        if (PlayerPrefs.GetInt(keyName) == 0)
            gameObject.SetActive(false);
    }
    public void SetActiveState (bool state) {
        string keyName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + gameObject.name;
        PlayerPrefs.SetInt(keyName, state ? -1 : 0);
        gameObject.SetActive(state);
    }
}

这将使用您当前的场景名称和附加的游戏对象名称作为键,因此您只需要确保使用此脚本的所有游戏对象都有不同的名称。

【讨论】:

  • SetActiveState(bool stat) 中 PlayerPrefs.SetInt() 的第一个参数应该是 keyName 吗?
  • 我真的认为这就是我要找的东西!我正在制作一个 2D RPG 入门套件,我可以使用它来使其成为开发人员的工具,因为 PlayerPrefs 可以很好地使用,因为我正在制作的不是在线。在我们说话时制作脚本并进行测试。
  • @JoeyL 哦,是的,你是对的,我错了。还有,祝你游戏好运:)
  • 非常感谢您抽出宝贵时间提供帮助。你和程序员都是非常了不起和耐心的人。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多