【问题标题】:Handling Collecting Player Data from Multiple Scripts [Unity]处理从多个脚本中收集玩家数据 [Unity]
【发布时间】:2019-04-24 18:10:19
【问题描述】:

我一直在开发一个保存系统来保存我的玩家数据,并且工作正常。但是,我不确定编译所有玩家数据的最佳方法是什么,因为它的所有属性(健康等)都分为不同的类,例如 PlayerHealthManager。现在我很确定我这样做的方式完全是一团糟,而且在很多地方可能都是错误的。

我有一个使用 Singleton 的基本 Player 类,并且基本上包含对我需要其数据的所有组件的引用,例如 PlayerHealthManager。然后我有一个 PlayerDataManager 类,它使用来自单例的信息将 Player 数据编译成一个结构并将其发送到 SaveSystem,但这感觉真的很混乱。下面附上代码。如果有人知道更好的做事方式或者这是正确的帮助,将不胜感激

public class PlayerDataManager : MonoBehaviour
{
    public static event Action<PlayerData> OnPlayerDataLoaded = delegate { };

    void Start()
    {
        PlayerData data = (PlayerData)SaveSystem.LoadPlayer();
        OnPlayerDataLoaded(data);
    }

    void OnDisable()
    {
        SavePlayerData();
    }

    public PlayerData GetPlayerData()
    {
        if (Player.instance != null)
        {
            var playerData = new PlayerData();
            Player p = Player.instance;

            // Players Health Fields
            playerData.health = p.HealthManager.Health;
            playerData.maxHealth = p.HealthManager.MaxHealth;

            // Player position fields
            playerData.position = new float[2];
            playerData.position[0] = p.transform.position.x;
            playerData.position[1] = p.transform.position.y;

            return playerData;
        }
        else
        {
            Debug.LogError("No player found");
            return new PlayerData();
        }

    }

    public void SavePlayerData()
    {
        SaveSystem.SavePlayer(GetPlayerData());
    }

}
[RequireComponent(typeof(PlayerHealthManager))]
public class Player : MonoBehaviour
{
    PlayerHealthManager healthManager;
    public static Player instance = null;

    public PlayerHealthManager HealthManager { get { return healthManager; } }
    void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    void OnEnable()
    {
        healthManager = GetComponent<PlayerHealthManager>();
        PlayerDataManager.OnPlayerDataLoaded += InitializeData;
    }

    void OnDisable()
    {
        PlayerDataManager.OnPlayerDataLoaded -= InitializeData;
    }

    void InitializeData(PlayerData data)
    {
        Vector2 newPosition = new Vector2(data.position[0], data.position[1]);
        transform.position = newPosition;

        healthManager.InitializeData(data);
    }
}

【问题讨论】:

  • 您如何将数据保存在您的 SaveSystem 中?
  • @Dave 抱歉,是的,我正在序列化数据应该已经提到了

标签: c# unity3d save


【解决方案1】:

我相信您正在序列化 SaveSystem 中的数据。使类/字段/属性可序列化(执行方法因您使用的序列化程序而异),因此您不必将数据克隆到另一个对象。

基本上你想摆脱GetPlayerDataPlayerData 并能够做到SaveSystem.SavePlayer(Player.instance); Player 类已经拥有所有信息,你可以决定什么应该序列化,什么不序列化。

如果您想将serialazble 数据保存在单独的类/结构PlayerData 中,请将PlayerData playerdata; 添加到您的Player 类中,并将PlayerHealthManager 和其他字段添加到PlayerData 类中。然后你可以做SaveSystem.SavePlayer(Player.instance.playerData);

在二进制序列化的情况下,我可以推荐协议缓冲区。它使序列化数据变得简单并且非常有效。您可以使用protobuf-net 进行快速集成。

【讨论】:

  • 您好,感谢您的帮助,我需要保留 PlayerData 结构,因为我使用它在其他地方传递数据,但我可以看到一起摆脱 PlayerDataManager 类会更容易.但是我只是不确定 Player 类是否是执行此操作的正确位置,因为 PlayerDataManager 也会加载数据,我认为在 Player 类中这样做会很奇怪,我可能需要在其中做其他事情未来
  • 没问题。看不出为什么在 Player 类中不能有一个 Load 方法来处理数据的加载。您还可以在 SaveSystem 中处理数据的加载。将其重命名为 SaveLoadSystem 并添加一个 LoadPlayer 方法。
猜你喜欢
  • 1970-01-01
  • 2020-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多