Система сохранений
MCE использует систему сохранений на основе JSON с именованными сохранениями, атомарной записью, ротацией автосохранений, версионированием и расширяемостью. Система сохранений хранит всё состояние игры игрока: команду, инвентарь, позицию, значки, прогресс квестов и игровые переменные.

Три переключателя на этом экране относятся к данной системе: Partida guardada выбирает формат сериализации, Autoguard. historia решает, записываются ли сюжетные моменты автоматически, а Subir a la nube — тот, что спрашивает разрешения, прежде чем данные покинут машину.
Архитектура
Система сохранений состоит из нескольких компонентов:
| Компонент | Назначение |
|---|---|
SavegameManager | Управляет операциями сохранения/загрузки (ScriptableObject, привязанный через SavegameInstaller) |
SavableObject | Базовый класс (ScriptableObject) для любого объекта, который хранит данные: SaveToText, LoadFromText и ResetSave |
MCESavesSerializer | JSON-сериализатор, используемый для каждого сохранённого текста |
GameVariables | Хранилище именованных переменных: булевых, целых, вещественных и строк |
GameVariableHolder | SavableObject, владеющий хранилищем GameVariables (GlobalGameData и каждый SceneInfoAsset — держатели) |
GameVariableReference | Ссылка в Inspector на одну переменную, используется узлами CommandGraph |
Migrations/ | ISaveMigration, SaveMigrationPipeline и SaveFormatVersions: версионирование сохранений |
Что сохраняется
SavegameManager.SavegameObjects — список сохраняемых объектов, входящих в каждое сохранение. Собственные объекты движка:
| Объект | Содержит |
|---|---|
GlobalGameData (сохраняется как SavableGlobalGameData) | Позиция игрока, деньги, полученные значки, игровые переменные, метка версии формата, секретная база и зал игрока |
Roster | Монстры команды с их полным состоянием (вид, уровень, IV, EV, характер, приёмы, PP, HP, статус, дружба...) |
MonsterStorage | Монстры в боксах |
Bag | Предметы и количества |
Dex | Учёт увиденных/пойманных по видам |
QuestManager | Активные квесты, выполненные цели, полученные награды |
CharacterData | Персонаж-игрок |
TimeManager | Время суток |
Nursery | Питомник для разведения |
SceneInfoAsset | Собственные игровые переменные каждой карты |
Файлы сохранений
Сохранение — это папка, а не один файл. Сохранения находятся в Saves/ внутри Application.persistentDataPath Unity:
| Платформа | persistentDataPath |
|---|---|
| Windows | %USERPROFILE%/AppData/LocalLow/<CompanyName>/<ProductName>/ |
| macOS | ~/Library/Application Support/<CompanyName>/<ProductName>/ |
| Linux | ~/.config/unity3d/<CompanyName>/<ProductName>/ |
| Android | Внутреннее хранилище (приватное для приложения) |
| iOS | Песочница приложения |
<persistentDataPath>/Saves/
2026-10-10-18-30-02/ a manual save, named with the current date
GlobalGameData.sav one .sav per savable object
Roster.sav
...
Manifest.txt the list of files a COMPLETE save must contain
Autosave/
OlderAutosave/
Сохранения записываются так, чтобы быть устойчивыми к сбоям:
- Каждый файл записывается атомарно (во временный файл, который затем заменяет исходный).
- Всё сохранение сначала записывается в папку
<name>.stagingи подставляется на место только после записи всех файлов и манифеста. Прерванное сохранение никогда не оставляет наполовину записанную смесь старого и нового состояния. - При загрузке отсутствие файла, указанного в манифесте, означает, что сохранение было прервано, поэтому оно отклоняется, а не загружается частично.
Сохранение и загрузка
Игрок сохраняется из меню паузы (пункт Exit предлагает сохранить, а клавиша сохранения в меню запрашивает подтверждение и записывает сохранение с именем по текущей дате) и загружается из главного меню (Continue загружает последнее сохранение, Load перечисляет все). Когда игра работает онлайн (MCE Online), прогресс хранит сервер, а локальное сохранение не записывается.
Из кода — через SavegameManager (редакции Source и Studio):
// A new save named with the current date
yield return savegameManager.SaveGameWithCurrentDate(playerCharacter);
// Rotate the autosave
yield return savegameManager.Autosave(playerCharacter);
// Load by name, or the most recent one
yield return savegameManager.LoadGame(saveName);
yield return savegameManager.LoadLastSavegame();
SavegameManager.GetAllSavegames(out list) и AreThereSavegames() сообщают, что есть на диске. Тестовые состояния сохранений (SaveStates) лежат рядом с сохранениями игрока под собственным префикс ом и скрыты из всех списков, которые видит игрок.
engine.SaveSystem (ISaveSystem) предоставляет Save(slot), Load(slot), HasSaveData(slot), DeleteSave(slot), OnSaved и OnLoaded, но в текущем движке он не подключён к SavegameManager: ни один обработчик не обрабатывает его запросы сохранения и загрузки, а HasSaveData ищет в persistentDataPath файл slot{N}.sav, который движок не записывает. Для настоящих сохранений используйте SavegameManager (редакции Source и Studio) или игровые меню. См. ISaveSystem.
Автосохранение
Две опции на экране Options (хранятся в GameplayConfigurationFile) управляют автосохранен ием:
| Опция | Когда сохраняет |
|---|---|
AutoSaveOnTeleporting | Каждый раз, когда игрок телепортируется на другую карту (не во время загрузки игры) |
AutoSaveOnStory | В сюжетных точках, где в графе есть узел AutoSaveIfEnabled |
Каждое автосохранение идёт в Autosave/; предыдущее перемещается в OlderAutosave/ только после успешной записи нового, поэтому прерванное автосохранение никогда не уничтожает последнее хорошее.
- Размещайте AutoSaveIfEnabled после сюжетного момента, а не посреди сражения или кат-сцены.
- Показывайте индикатор автосохранения во время сохранения.
Версионирование сохранений
Сохранения несут версию формата, которая записывается в SavableGlobalGameData при сохранении и сравнивается при загрузке через SaveMigrationPipeline, запускающий миграции, нужные более старому сохранению:
| Версия | Название | Значение |
|---|---|---|
| 0 | LegacyHashes | Сохранения до появления метки версии: виды, формы, способности, приёмы и предметы определяются по хешу времени выполнения от имён их ассетов |
| 1 | StableNames | Определяет их по именам ассетов (стабильным строкам). Это текущая версия |
Когда формат меняется, в конвейер добавляется новая ISaveMigration, а SaveFormatVersions.Current увеличивается.
Никогда не переименовывайте сериализованные поля в классах, связанных с сохранениями, без миграции, и считайте имена ассетов видов, приёмов, способностей и предметов ключами сохранений: переименование ассета ломает сохранения, которые его упоминают. Если вы переименуете поле, существующие файлы сохранений потеряют эти данные при загрузке; для переименования полей используйте [FormerlySerializedAs("oldName")].
GameVariables
Система GameVariables — хранилище постоянных именованных значений MCE. Узлы CommandGraph и скрипты читают и записывают её, и она сохраняется вместе с объектом-владельцем.
Типы переменных
| Тип | Описание | Пример |
|---|---|---|
| Boolean | Флаги «истина/ложь» | defeatedBrock = true |
| Integer | Числовые счётчики | fishCaught = 42 |
| Float | Десятичные числа | rivalTrust = 0.5 |
| String | Текстовые значения | rivalName = "Gary" |
Каждая переменная живёт в держателе: глобальном (GlobalGameData) или в SceneInfoAsset карты. Переменная, определённая на карте, локальна для этой карты; глобальная общая для всей игры.
Использование в CommandGraph
- SetBoolVariable, SetIntVariable: задают значение переменной.
- IfBool, IfIntEquals, IfIntCompare, SwitchIntVariable: ветвление по переменной.
У каждого из этих узлов есть ссылка на переменную, где вы выбираете держателя, тип и имя.