#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.