Модель — это чистые данные.
Это класс или структура, которые содержат только поля и свойства, без методов и логики.
Пример:
[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; }- Всё! Ты можешь использовать этот модуль даже с одним классом.