Обработка сбора данных игрока из нескольких сценариев [Unity]

#c# #unity3d #save

#c# #unity3d #Сохранить

Вопрос:

Я работал над системой сохранения данных моих игроков, и она работает нормально. Однако я не уверен, какой наилучший способ скомпилировать все данные моих игроков, поскольку все его атрибуты (здоровье и т.д.) Разделены на разные классы, например PlayerHealthManager. Прямо сейчас я почти уверен, что то, как я это делаю, является полным беспорядком и, вероятно, неправильным во многих местах.

У меня есть базовый класс Player, который использует синглтон и в основном содержит ссылки на все компоненты, данные которых мне нужны, например, PlayerHealthManager. Затем у меня есть класс PlayerDataManager, который использует информацию из синглтона для компиляции данных игрока в структуру и отправки их в систему сохранения, однако это кажется действительно беспорядочным. Код прилагается ниже. Если кто-нибудь знает лучший способ сделать что-то, или если это правильно, помощь будет высоко оценена

 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. Как вы сохраняете данные в своей системе сохранения?

2. @Dave извините, да, я сериализую данные, должен был упомянуть, что

Ответ №1:

Я полагаю, что вы сериализуете данные в своем SaveSystem . Сделайте классы / поля / атрибуты сериализуемыми (способы сделать это различны в зависимости от используемого вами сериализатора), чтобы вам не приходилось клонировать данные в другой объект.

В принципе, вы хотите избавиться от GetPlayerData и PlayerData и иметь возможность делать SaveSystem.SavePlayer(Player.instance); Класс Player уже имеет всю информацию, и вы можете решить, что следует сериализовать, а что нет.

Если вы хотите сохранить данные serialazble в отдельном классе / структуре, PlayerData добавьте PlayerData playerdata; в свой класс Player и добавьте PlayerHealthManager и другие поля в класс PlayerData. Затем вы могли бы сделать SaveSystem.SavePlayer(Player.instance.playerData);

В случае двоичной сериализации я могу порекомендовать буферы протокола. Это упрощает сериализацию данных и делает ее очень эффективной. Вы можете использовать protobuf-net для быстрой интеграции.

Комментарии:

1. Привет, спасибо за помощь, мне нужно сохранить структуру PlayerData, поскольку я использую ее для передачи данных в другом месте, но я вижу, как было бы проще просто избавиться от класса PlayerDataManager все вместе. Однако я просто не был уверен, что класс Player является подходящим местом для этого, поскольку PlayerDataManager также выполняет загрузку данных, что, как мне показалось, было бы странно делать в классе Player, который мне может понадобиться для выполнения других действий в будущем

2. Нет проблем. Не вижу причин, по которым у вас не могло бы быть метода Load в классе Player, который обрабатывал бы загрузку данных. Вы также можете обрабатывать загрузку данных в SaveSystem. Переименуйте его в SaveLoadSystem и добавьте метод LoadPlayer.