处理从多个脚本收集播放器数据[Unity]

时间:2019-04-23 22:10:37

标签: c# unity3d save

我一直在使用保存系统来保存我的播放器数据,并且工作正常。但是,由于所有属性(健康状况等)都分为不同的类(例如PlayerHealthManager),因此我不确定什么是编译所有Players Data的最佳方法。现在,我很确定自己的操作方式完全是一团糟,而且在很多地方可能是错误的。

我有一个基本的Player类,该类使用Singleton,基本上持有对我需要其数据的所有组件的引用,例如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);
    }
}

1 个答案:

答案 0 :(得分:1)

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

基本上,您希望摆脱GetPlayerDataPlayerData并能够进行SaveSystem.SavePlayer(Player.instance); Player类已经拥有所有信息,并且您可以决定应该序列化什么,而不必序列化什么。

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

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