Skip to content
E
Egmatic
система сохраненийсохранение прогрессасериализациясостояние игрыфайл сохранения

Как сделать систему сохранений в игре: руководство для разработчиков

Система сохранений делает одно — превращает состояние игры в данные, записывает их в хранилище и потом читает обратно, восстанавливая всё как было. Сложности возникают в другом: что именно сохранять, как не допустить повреждения файла и как сохранить работоспособность старых слотов после обновления игры. Это руководство разбирает, что входит в сохранение, форматы сериализации на выбор (JSON, бинарный, protobuf), приём атомарной записи, защищающий файлы от порчи, и версионирование формата, благодаря которому обновления не ломают старые слоты. Написано для соло-разработчиков и маленьких студий, опирается на то, как хранилище и сериализация работают на самом деле, — без выдуманных процентов.

Vladislav Kovnerov10 июля 2026 г.10 мин

У системы сохранений одна задача: взять состояние игры, превратить его в данные, записать в хранилище и позже прочитать обратно, восстановив игру ровно такой, какой она была. Читать и писать несложно. Но настоящие трудности — другие, и их три: решить, что именно считать состоянием, заслуживающим сохранения; писать так, чтобы файл никогда не повредился; и сохранить работоспособность старых слотов после того, как вы измените игру.

Это руководство — практическая версия для соло-разработчиков и маленьких студий. Здесь разобрано, что входит в сохранение, форматы сериализации на выбор, единственный приём, защищающий от порчи, и способ версионировать данные так, чтобы обновление не сломало каждый слот, который сделали ваши игроки. Всё опирается на то, как хранилище и сериализация работают на самом деле, — без выдуманных цифр про удержание.

Сохраняйте состояние, а не производные данные

Первое решение — что сохранять. Правило простое: сохраняйте данные, которые определяют прогресс игрока, а всё остальное пересчитывайте заново.

Сохраняйте то, что игрок заработал или выбрал, — позицию персонажа, инвентарь, текущий уровень, пройденные задачи, открытые способности, сюжетные решения и настройки вроде уровней звука и схемы управления. Не сохраняйте ничего, что можно вычислить: кэшированные позиции врагов, заранее посчитанные итоги, временное визуальное состояние.

СохраняемПересчитываем заново
Позиция игрока, здоровье, инвентарьПозиция камеры, текущий кадр анимации
Отметки о пройденных уровнях, открытый контентКэш поиска пути, производные итоги счёта
Сюжетные решения, настройкиПозиции частиц, временные эффекты

Причина убрать производные данные — не только размер. Если вы храните величину, которую можно пересчитать, и логика игры меняется, сохранённое значение превращается в противоречие. Слот, в котором лежат и исходные данные, и устаревший производный итог, начнёт расходиться сам с собой. Сохраняйте источник, остальное пересчитывайте — и слот всегда остаётся внутренне непротиворечивым.

Выберите формат сериализации

Сериализация — это превращение объектов из памяти в байты, которые можно хранить, и обратно. Три формата покрывают почти любую игру.

ФорматЧитаемостьРазмерСкоростьДля чего подходит
JSONДа (текст)КрупнееСредняяРазработка и большинство небольших игр
БинарныйНетМаленькийБыстрыйОбъёмные сохранения, чувствительные к скорости загрузки
Protocol Buffers (protobuf)Нет (но со схемой)МаленькийБыстрыйСтрогие схемы, разные языки

Лучший выбор для небольшой игры — JSON. Файл сохранения, который можно открыть в текстовом редакторе и прочитать, стоит гораздо больше байтов, сэкономленных бинарным форматом: когда слот сломается у реального игрока, вам захочется его прочитать. Переходите на бинарный формат или protobuf, только если сохранения настолько велики или загрузка настолько медленна, что размер реально мешает. Для большинства 2D-игр этого не случается.

Одно замечание о компромиссе с читаемостью: сохранение, которое можно прочитать человеком, — это и файл, который любопытный или злонамеренный игрок может отредактировать. Для одиночной игры это нормально, а для моддерского сообщества — скорее плюс. Относитесь к этому как к обстоятельству, которое стоит учитывать, а не как к препятствию.

Приём атомарной записи

Это самый важный приём во всём руководстве — и именно его большинство инди-игр делают неправильно.

Наивный подход — открыть файл сохранения и писать прямо в него. Проблема в том, что запись не мгновенна, и если игра падает, устройство теряет питание или операционная система прерывает процесс на середине, остаётся файл, наполовину состоящий из старых данных, а наполовину — из новых: повреждённый слот, который игра не сможет прочитать.

Решение — никогда не писать в рабочий файл напрямую. Вместо этого:

  1. Запишите новые данные сохранения во временный файл.
  2. Переименуйте временный файл поверх настоящего.

Переименование файла — атомарная операция на одном томе: она либо выполняется целиком, либо не выполняется вовсе. Падение при записи оставляет временный файл недописанным, но настоящий слот сохранений не тронут и по-прежнему работоспособен. Падение при переименовании безопасно, потому что операционная система гарантирует атомарность самого переименования. Игрок либо сохраняет старый слот, либо получает новый, — но никогда не получает половину.

Момент сбояРезультат
Падение при записи временного файлаСтарый слот цел, временный файл испорчен (его отбрасываем)
Падение при переименованииОдин из двух файлов цел, смесь невозможна
Чистое завершениеНовый слот заменяет старый

Этот приём почти ничего не стоит реализовать и убирает практически все повреждения от потери питания и падений. Вместе с одним-двумя резервными слотами он превращает потерю сохранений из рядового обращения в поддержку в редкое событие.

Версионируйте формат сохранений

День релиза — это день, когда ваш формат сохранений становится контрактом. У игроков будут лежать слоты под каждую версию игры, которую вы когда-либо выпустите, и каждый должен загружаться.

Храните номер версии в каждом файле сохранения и никогда не предполагайте заранее структуру данных при загрузке:

  • При загрузке читайте версию первой.
  • Переносите старые форматы в актуальный по шагам — с версии 1 на 2, затем с 2 на 3.
  • Каждому отсутствующему полю назначайте разумное значение по умолчанию.
  • Переименованные поля связывайте с новыми именами.

Дисциплина в том, чтобы менять формат только через миграцию. Добавили поле — поднимите версию и напишите миграцию, которая заполнит значение по умолчанию для старых слотов. Никогда не меняйте молча смысл существующего поля: старый слот игрока загрузит старый смысл под новый код и сломается.

ИзменениеБезопасная миграция
Добавили новое полеЗначение по умолчанию для старых слотов
Убрали полеПерестаём его читать; игнорируем в старых слотах
Переименовали полеСвязываем старое имя с новым в загрузчике
Изменили смысл значенияНовый номер версии, явное преобразование

Версионируемый формат с миграциями — это и есть разница между игрой, чьи обновления сохраняют старые слоты, и игрой, чьи обновления стирают прогресс игроков. Второго игроки не прощают.

Когда и где сохранять

Два независимых вопроса: где живут данные и как часто вы их записываете.

Где — отчасти решение платформы. Локальные файлы — базовый уровень. Платформенные облачные системы (сети консолей, специфичный для платформы обмен) реплицируют сохранения между устройствами, чего игроки и ждут, но это добавляет правила разрешения конфликтов: когда облачный и локальный слот расходятся, нужна политика, обычно «побеждает самый свежий». Проектируйте разрешение конфликта до того, как столкнётесь с ним.

Как часто — проектное решение с техническими последствиями:

  • Сохранение в контрольных точках пишет только в определённые моменты (конец уровня, комната сохранения). Просто, надёжно и намеренно заложено в сложность игры.
  • Автосохранение пишет периодически или по значимым событиям. Удобно, но никогда не должно блокировать игру или вызывать рывок — сохраняйте в фоновом потоке или между кадрами.
  • Сохранение в любом месте даёт игроку полный контроль, но обнажает каждый граничный случай в сериализации состояния, потому что игрок может сохранить в любой момент.

Техническое правило, покрывающее все три варианта: никогда не сохраняйте на горячем участке так, чтобы игрок это почувствовал. Сериализация и запись на диск занимают время; делайте их там, где в кадровом бюджете есть запас.

Частые ошибки

  • Сохранять производные данные. Храните исходное состояние, остальное пересчитывайте, иначе после обновления слот начнёт противоречить сам себе.
  • Писать прямо в рабочий файл сохранения. Падение на середине записи портит его. Пишите во временный файл и переименовывайте.
  • Нет номера версии. Первое же обновление ломает все существующие слоты.
  • Блокировать главный поток. Сохранение, из-за которого игра дёргается, игрок чувствует каждый раз.
  • Один слот и без резерва. Единственное повреждённое сохранение теряет всё. Держите резервный слот.
  • Рассчитывать, что облако решит конфликты. Оно их порождает; заранее определите политику разрешения.
  • Сохранение везде как замена проектированию. «Сохранить в любом месте» удобно для игрока, но труднее всего сериализовать правильно — выбирайте это сознательно, а не по умолчанию.

Роль Egmatic

Egmatic построен вокруг версионируемых данных в JSON. Редактор выдаёт игровые данные в виде структурированного JSON, который движок затем читает, поэтому сериализация — полноценная часть архитектуры, а не пристройка, появившаяся под конец. Та же дисциплина напрямую переносится на сохранения: чистый, версионируемый, читаемый формат, который можно просмотреть, когда что-то пошло не так, и переносить на новые версии, когда игра меняется. Живой предпросмотр Egmatic позволяет сохранить, перезагрузить и убедиться, что состояние восстанавливается точно, — превращая самую скучную часть разработки сохранений, проверку того, что слот корректно проходит туда-обратно, в быстрый цикл вместо медленной пересборки.

За привычками сериализации, на которые опирается эта статья, наше руководство о MonoGame объясняет базу на C#, на которой построен Egmatic, а руководство по производительности 2D разбирает дисциплину удержания работы вне горячего участка — то же правило, благодаря которому сохранение не вызывает рывков.

Заключение

Система сохранений — это не функция, которую добавляют на последней неделе. Это дисциплина: сохранять исходное состояние, а не производные данные; выбирать формат, который можно отлаживать; писать атомарно, чтобы падение никогда не испортило файл; и версионировать формат, чтобы обновления никогда не ломали прогресс игрока. Сделайте эти четыре вещи правильно — и сохранения перестанут быть обузой для поддержки и станут невидимыми, какими им и положено быть.