https://github.com/rimurudev/crossplatformpersistentprogress-simpleexample
Пример кросс-платформенной сейв системы и работы с данными (прогрессом). Без UniRx или R3 а так же без Zenject (DI). Простой примерчик.
https://github.com/rimurudev/crossplatformpersistentprogress-simpleexample
persistent-progress-service rimuru-dev rimurudev save save-system unity-persistent-progress unity-persistentprogress unity-save
Last synced: 7 months ago
JSON representation
Пример кросс-платформенной сейв системы и работы с данными (прогрессом). Без UniRx или R3 а так же без Zenject (DI). Простой примерчик.
- Host: GitHub
- URL: https://github.com/rimurudev/crossplatformpersistentprogress-simpleexample
- Owner: RimuruDev
- License: mit
- Created: 2025-01-15T13:56:25.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-01-15T14:19:03.000Z (about 1 year ago)
- Last Synced: 2025-01-15T15:54:15.281Z (about 1 year ago)
- Topics: persistent-progress-service, rimuru-dev, rimurudev, save, save-system, unity-persistent-progress, unity-persistentprogress, unity-save
- Language: C#
- Homepage:
- Size: 1.53 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Руководство по работе с модулем сохранений
## Основные термины
### Модель
Модель — это **чистые данные**.
Это класс или структура, которые содержат только поля и свойства, без методов и логики.
**Пример:**
```csharp
[Serializable]
public class UserProgress
{
public string UserId;
public string UserName;
public int Coins;
public int Crystals;
}
```
### Прокси
**Прокси** — это обертка над моделью, которая полностью повторяет её интерфейс.
Прокси используется для:
1. **Валидации данных** перед их изменением.
2. **Подписки на изменения данных** через события.
3. **Безопасного управления источником данных**.
**Пример:**
```csharp
public class UserProgressProxy
{
public event Action 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);
}
}
}
```
---
## Устройство модуля
### Основная идея
Модуль разделяет **данные (модели)** и **логику работы с данными (прокси)**.
Кроме того, он построен на принципах **абстракции** и **расширяемости**.
### Этапы работы
1. **Определяем данные, которые нужно сохранять (модели).**
2. **Создаем прокси для работы с этими данными.**
3. **Реализуем `IStorageService` — интерфейс для управления сохранением.**
---
### Интерфейс API: `IStorageService`
Интерфейс описывает базовые операции для работы с сохранениями:
- `SaveProgress()` — сохранить данные.
- `LoadProgress()` — загрузить данные.
- `DeleteAllProgress()` — удалить данные.
**Пример интерфейса:**
```csharp
public interface IStorageService : IDisposable
{
public UserProgressProxy UserProgress { get; }
...
public void SaveProgress();
public void LoadProgress();
public void DeleteAllProgress();
}
```
**Расширение интерфейса:**
Если нужно добавить новый тип данных, достаточно:
1. Создать новую модель.
2. Написать для неё прокси (по желанию).
3. Добавить её в `IStorageService` как новое свойство.
---
### Реализации интерфейса
#### 1. `MobileGameStorageService`
Класс для сохранения данных на Android и iOS.
**Методы:**
- `SaveProgress()` — сохраняет данные на диск в формате JSON.
- `LoadProgress()` — загружает данные с диска и оборачивает их в прокси.
- `DeleteAllProgress()` — удаляет файлы данных с диска.
#### 2. `YandexGameStorageService`
Класс для интеграции с API Яндекс Игр (WebGL).
**Методы:**
- `SaveProgress()` — вызывает метод сохранения в плагине Яндекса.
- `LoadProgress()` — не используется (данные загружаются автоматически через плагин).
- `DeleteAllProgress()` — вызывает сброс прогресса через API плагина.
---
## Как всё это работает?
Модуль использует **единый интерфейс** для всех платформ.
**Класс `StaticProgressService`** автоматически выбирает нужную реализацию (например, `MobileGameStorageService` для Android) на основе текущей платформы.
### Как создается нужная реализация?
**Пример:**
```csharp
private static IStorageService CreateStorageService()
{
#if UNITY_WEBGL
return new YandexGameStorageService();
#elif UNITY_ANDROID
return new MobileGameStorageService();
#else
throw new System.NotSupportedException("Unsupported platform");
#endif
}
```
### Как использовать модуль в коде?
#### Загрузка данных:
```csharp
StaticProgressService.Instance.Load();
```
#### Сохранение данных:
```csharp
StaticProgressService.Instance.Save();
```
#### Изменение данных:
```csharp
StaticProgressService.Instance.UserProgress.Coins += 100;
```
#### Подписка на изменения:
```csharp
StaticProgressService.Instance.UserProgress.OnCoinsChanged += coins =>
{
Debug.Log($"Монеты изменились: {coins}");
};
```
---
## Преимущества модуля
1. **Единый API**
Не важно, где и как ты сохраняешь данные — структура интерфейса остаётся неизменной.
2. **Расширяемость**
Легко добавить новый способ сохранения (например, удалённый сервер или SD-карту).
3. **Гибкость**
Поддерживает как один класс для всех данных (`GameData`), так и множество отдельных моделей.
4. **Лёгкость замены**
Можно легко заменить способ сериализации (например, с `JsonUtility` на `Newtonsoft.Json`) в одном месте.
5. **Поддержка событий**
Удобно отслеживать изменения данных через прокси.
---
## Минимальный пример для небольших проектов
Если ты используешь всего один класс данных (например, `GameData`), то достаточно:
1. Создать модель:
```csharp
[Serializable]
public class GameData
{
public int Coins;
public string PlayerName;
}
```
2. Добавить её в реализацию `IStorageService`:
```csharp
public GameDataProxy GameData { get; private set; }
```
3. Всё! Ты можешь использовать этот модуль даже с одним классом.
---