Модель — это чистые данные.
Это класс или структура, которые содержат только поля и свойства, без методов и логики.
Пример:
[Serializable]
public class UserProgress
{
public string UserId;
public string UserName;
public int Coins;
public int Crystals;
}Прокси — это обертка над моделью, которая полностью повторяет её интерфейс.
Прокси используется для:
- Валидации данных перед их изменением.
- Подписки на изменения данных через события.
- Безопасного управления источником данных.
Пример:
public class UserProgressProxy
{
public event Action<int> OnCoinsChanged;
public UserProgress Origin { get; private set; }
public UserProgressProxy(UserProgress origin)
{
Origin = origin;
}
public int Coins
{
get => Origin.Coins;
set
{
Origin.Coins = value;
OnCoinsChanged?.Invoke(value);
}
}
}Модуль разделяет данные (модели) и логику работы с данными (прокси).
Кроме того, он построен на принципах абстракции и расширяемости.
- Определяем данные, которые нужно сохранять (модели).
- Создаем прокси для работы с этими данными.
- Реализуем
IStorageService— интерфейс для управления сохранением.
Интерфейс описывает базовые операции для работы с сохранениями:
SaveProgress()— сохранить данные.LoadProgress()— загрузить данные.DeleteAllProgress()— удалить данные.
Пример интерфейса:
public interface IStorageService : IDisposable
{
public UserProgressProxy UserProgress { get; }
...
public void SaveProgress();
public void LoadProgress();
public void DeleteAllProgress();
}Расширение интерфейса:
Если нужно добавить новый тип данных, достаточно:
- Создать новую модель.
- Написать для неё прокси (по желанию).
- Добавить её в
IStorageServiceкак новое свойство.
Класс для сохранения данных на Android и iOS.
Методы:
SaveProgress()— сохраняет данные на диск в формате JSON.LoadProgress()— загружает данные с диска и оборачивает их в прокси.DeleteAllProgress()— удаляет файлы данных с диска.
Класс для интеграции с API Яндекс Игр (WebGL).
Методы:
SaveProgress()— вызывает метод сохранения в плагине Яндекса.LoadProgress()— не используется (данные загружаются автоматически через плагин).DeleteAllProgress()— вызывает сброс прогресса через API плагина.
Модуль использует единый интерфейс для всех платформ.
Класс StaticProgressService автоматически выбирает нужную реализацию (например, MobileGameStorageService для Android) на основе текущей платформы.
Пример:
private static IStorageService CreateStorageService()
{
#if UNITY_WEBGL
return new YandexGameStorageService();
#elif UNITY_ANDROID
return new MobileGameStorageService();
#else
throw new System.NotSupportedException("Unsupported platform");
#endif
}StaticProgressService.Instance.Load();StaticProgressService.Instance.Save();StaticProgressService.Instance.UserProgress.Coins += 100;StaticProgressService.Instance.UserProgress.OnCoinsChanged += coins =>
{
Debug.Log($"Монеты изменились: {coins}");
};-
Единый API
Не важно, где и как ты сохраняешь данные — структура интерфейса остаётся неизменной. -
Расширяемость
Легко добавить новый способ сохранения (например, удалённый сервер или SD-карту). -
Гибкость
Поддерживает как один класс для всех данных (GameData), так и множество отдельных моделей. -
Лёгкость замены
Можно легко заменить способ сериализации (например, сJsonUtilityнаNewtonsoft.Json) в одном месте. -
Поддержка событий
Удобно отслеживать изменения данных через прокси.
Если ты используешь всего один класс данных (например, GameData), то достаточно:
- Создать модель:
[Serializable]
public class GameData
{
public int Coins;
public string PlayerName;
}- Добавить её в реализацию
IStorageService:
public GameDataProxy GameData { get; private set; }- Всё! Ты можешь использовать этот модуль даже с одним классом.