Используя сохраняемые данные, вы можете отслеживать и сохранять данные каждого игрока между игровыми сеансами. Это позволяет использовать множество прогрессивных режимов игры, в которых игроки могут выходить, а затем возвращаться, чтобы возобновить выполнение своих целей или застать то же состояние игры, в котором они вышли.
Сохраняемые данные работают путём хранения данных для каждого отдельного игрока, таких как его профиль или статистика, в Verse. Эти данные затем можно обновлять столько раз, сколько изменяется значение данных. Поскольку эти данные сохраняются, они будут сохраняться во время игровых сеансов и будут доступны в любое время, когда игрок находится в игре онлайн.
Выживание, Экономический симулятор, RPG и Roguelite — лишь некоторые примеры игровых режимов, в которых используются сохраняемые данные. В таких режимах от игроков требуется накапливать предметы для достижения долгосрочных целей игрового процесса.
Используйте в сценариях Verse сохраняемые данные, отдельные для каждого игрока, с помощью модулей. Задействуйте сохраняемые данные в режимах игры, в которых вы хотели бы удержать игроков, стимулируя постоянный прогресс.
Чтобы самостоятельно попрактиковаться в реализации сохраняемости, ознакомьтесь с уроком Сохраняемая статистика игрока.
Помимо того, что сохраняемые данные можно создавать и использовать в Verse, их базовые функции также поддерживают некоторые из устройств творческого режима. Подробнее об этом см. в статье Постоянные устройства.
Что означает сохраняемость в Verse
В Verse переменная, определённая в модуле, является глобальной для любого активного экземпляра игры, в область видимости которого эта переменная входит. Переменные области видимости модуля, за исключением тех, что связаны с сеансом, должны быть сохраняемыми — иметь возможность хранения данных за пределами текущей игры. Поэтому типы, используемые в области модуля, ограничены.
В области модуля можно использовать следующие типы:
| Допустимые типы в области видимости модуля | Определение | Ограничения |
|---|---|---|
| Данные любого типа, представленные | Данные сохраняются только во время текущего сеанса и не сохраняются для последующих раундов. |
| Данные любого типа, представленные | Доступ к сохраняемым данным игрока разрешён только тогда, когда игрок находится в текущей игре. |
Если игрок покидает игру или не участвует в текущем сеансе, вы больше не сможете хранить его данные или получать к ним доступ в этом игровом сеансе. Если игрок возвращается или снова начинает играть в ту же игру, вы можете получить доступ к его данным и обновить их.
Создание сохраняемых данных в Verse
Вы можете создавать собственные сохраняемые данные для каждого игрока, которые можно будет постоянно обновлять, сохранять и вызывать всякий раз, когда игроки вновь присоединяются к игре. Во время подбора игроков игра проверит наличие сохраняемых данных для нового игрока. Если у игрока имеются сохраняемые данные, они загружаются и становятся доступны для сценариев Verse.
Если у игрока имеются сохраняемые данные для острова и загрузка данных не удалась, игрок не сможет присоединиться к острову. Это защитная мера, которая предотвратит перезапись сохраняемых данных в случае сбоя загрузки данных.
Чтобы создать сохраняемые данные в коде Verse, определите глобальную переменную strong_map, которая использует тип игрока в качестве ключа, а сохраняемый тип — в качестве значения. См. раздел Сохраняемые типы, чтобы ознакомиться с полным списком типов, которые могут сохраняться.
В следующем примере глобальная переменная weak_map MySavedPlayerData использует тип игрока в качестве ключа, а целое число — в качестве значения. Хранение целочисленного значения для игрока в этой переменной означает, что данные будут сохраняться во время игровых сеансов и могут быть доступны и обновлены в любое время, когда игрок находится в игре.
var MySavedPlayerData:weak_map(player, int) = map{}
После определения сохраняемых данных нужно будет инициализировать данные для каждого игрока. Вы можете сделать это, проверив наличие других сохранённых данных для этого игрока, а затем добавив игрока и начальное значение в weak_map.
# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void =
InitialSavedPlayerData:int = 0
Players := GetPlayspace().GetPlayers()
for (Player : Players):
if:
not MySavedPlayerData[Player]
set MySavedPlayerData[Player] = InitialSavedPlayerDataВ предыдущем примере хранилось только одно целочисленное значение, но вы можете использовать другие типы, например классы и массивы, для хранения большего количества данных для каждого игрока в weak_map. Полный список типов, которые можно использовать, см. в разделе Сохраняемые типы.
В следующем примере Verse показано, как можно определить собственный профиль игрока в классе, который можно будет хранить, обновлять и открываться игроком позднее. Класс player_profile_data хранит информацию игрока, такую как полученный им опыт, его рейтинг и завершенные им задания.
player_profile_data := class<final><persistable>:
Version:int = 0
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0
CompletedQuestCount:int = 0
QuestHistory:[]string = array{}
var PlayerProfileDataMap:weak_map(player, player_profile_data) = map{}Существует ограничение на объём данных, которые вы можете хранить на каждого игрока и остров. Каждый раз, когда вы сохраняете данные, мы рекомендуем проверять, как ваши обновления влияют на общий размер, используя функцию 'FitsInPlayerMap'. Для получения более подробной информации ознакомьтесь с разделом Проверка допустимых пределов объёма сохраняемых данных.
Теперь, когда вы знаете, как создавать сохраняемые данные и инициализировать их для каждого игрока, обязательно ознакомьтесь с разделом Рекомендации по использованию, в котором приведены рекомендуемые способы работы с сохраняемыми данными в Verse!
Изменение данных в опубликованных версиях острова
Если после публикации текущей версии вашего острова вы обновите сохраняемые данные, любые сохранённые данные из предыдущей версии острова должны будут поддерживаться в более поздних версиях острова.
Чтобы это гарантировать, в UEFN выполняется проверка обратной совместимости. Если код Verse больше не совместим с текущей опубликованной версией, происходит сбой компиляции. Эта проверка обратной совместимости запускается каждый раз, когда вы:
нажимаете Запуск сеанса на панели инструментов UEFN;
нажимаете Применить изменения или Применить изменения Verse на панели инструментов UEFN;
первый раз публикуете остров;
активируете новую публичную версию своего острова.
Эта проверка обратной совместимости фактически представляет собой проверку типа значения переменной weak_map в области видимости модуля. Для простых типов, таких как целые числа, тип нельзя изменить после публикации острова. Сюда входят struct, определение структуры которых невозможно изменить после публикации острова.
В настоящее время единственный сохраняемый тип, к которому можно добавить дополнительные данные после публикации острова, — это тип class (если новые поля имеют значения по умолчанию). Это означает, что загрузка сохранённых данных из предыдущей версии будет включать новые поля и их значения по умолчанию. Для получения более подробной информации ознакомьтесь с рекомендациями по использованию классов в качестве сохраняемых данных.
Сброс сохраняемых данных для вашего острова
Если вам когда-нибудь понадобится сбросить сохраняемые данные своего острова, вы можете сделать это в Verse, назначив значение по умолчанию для сохраняемых данных в weak_map для игрока, когда он присоединяется к острову.
Чтобы узнать, были ли данные игрока уже сброшены, вы можете включить значение версии для своего класса и обновлять его новыми изменениями в рамках ваших сохраняемых данных. Это лишь один из вариантов, представленных ниже. Обязательно ознакомьтесь с остальными!
Сохраняемые типы в Verse
Далее приведены типы сохраняемых данных, которые можно использовать в переменной weak_map области видимости модуля:
| Тип | Описание |
|---|---|
array | Массив является сохраняемым, если тип элементов массива является сохраняемым. |
char32 | Значения символов являются сохраняемыми. |
char8 | Значения символов являются сохраняемыми. |
class | Класс является сохраняемым в следующих случаях:
|
Значения цвета являются сохраняемыми. | |
enum | enum является сохраняемым, если определён с помощью спецификатора persistable. |
float | Значения с плавающей запятой являются сохраняемыми. |
int | Целочисленные значения являются сохраняемыми. |
logic | Логические значения являются сохраняемыми. |
map | Ассоциативный массив является сохраняемым, если типы ключа и значения являются сохраняемыми. |
option | Переменные типа option являются сохраняемыми. |
struct | Структура является сохраняемой в следующих случаях:
Изменить сохраняемую структуру после публикации своего острова невозможно. По этой причине мы рекомендуем использовать сохраняемые структуры только в том случае, если известно, что схема постоянна. кортеж |
tuple | Кортеж является сохраняемым, если каждый тип элемента является сохраняемым. |
Значения vector2 являются сохраняемыми. | |
Значения vector2i являются сохраняемыми. | |
Значения vector3 являются сохраняемыми. |
Тестирование с сохраняемыми данными
Если вы хотите протестировать поведение сохраняемых данных перед публикацией последней версии острова, вы можете настроить следующее поведение на своём устройстве Настройки острова как для параметра Алгоритм сохранения: сеанс тестирования, так и для параметра Алгоритм сохранения: сеанс редактирования:
| Поведение сохраняемых данных | Описание |
|---|---|
Импорт из актуальных данных | Импортировать данные сеанса из актуальных данных, если такие данные доступны. Для этого необходимо, чтобы остров был опубликован на игровом сервера, и чтобы игрок играл на опубликованной версии острова. Если доступны актуальные данные, данные сеанса игрового тестирования будут заполнены копией актуальных данных. Это может оказаться очень полезно для тестирования проблем с сохраняемыми данными, связанных с изменениями в логике острова. |
Симуляция нового пользователя | Запускает игрока с новыми сохраняемыми данными, как если бы он впервые играл на острове. |
Поведение вариантов Импорт из актуальных данных и Симуляция нового пользователя работают как для сохранения данных с помощью Verse, так и для постоянных устройств, таких как Точка сохранения и Управление заданиями. Симуляция нового пользователя запустит сеанс с пустыми данными как для сохранения данных с помощью Verse, так и для постоянных устройств без изменения актуальных данных, а Импорт из актуальных данных загрузит сохраняемые данные из обоих, если доступны актуальные данные.
Настройки поведения сохраняемых данных применяются во время игрового тестирования. Существует два разных сценария, в которых можно протестировать сохраняемые данные:
Сеанс редактирования: настройки поведения сохраняемых данных применяются при запуске сеанса из UEFN. Это означает, что сохраняемые данные могут сохраняться в нескольких играх в течение одного сеанса. Если вы выйдете из сеанса и перезапустите новый сеанс, сохраняемые данные будут сброшены, а настройки поведения сохраняемых данных будут применены повторно.
Сеанс игрового тестирования: настройки поведения сохраняемых данных применяются при настройке игрового тестирования на творческом портале, когда тестировщик присоединяется через код для игрового тестирования или код частной ссылки. Настройки поведения сохраняемых данных применяются только при первом присоединении игрока. Когда игрок прекращает игровой тест и снова присоединяется к нему, его данные сохраняются на протяжении всех сеансов, а настройки поведения данных сохранения не применяются повторно. Чтобы сбросить сохраняемые данные, вам нужно будет создать новый код ссылки для игрового тестирования.
Для обновлений острова, которые влияют на управление и обновление сохраняемых данных, мы рекомендуем протестировать оба сценария: запуск сеанса из UEFN и игровой тест с использованием кода ссылки. Обязательно протестируйте изменения, вносимые в сохраняемые данные, как с использованием актуальных данных, так и с симуляцией новых пользовательских данных. Это поможет гарантировать, что ваши обновления будут действовать как для текущих игроков вашего острова, так и для новых игроков.
Эффекты публикации новых версий вашего острова
После публикации вашего острова для игроков создаётся запись сохраняемых данных, когда данные игроков сохраняются в weak_map. Эти данные затем будут сохраняться и загружаться при любых последующих посещениях вашего острова.
Если будут опубликованы новые версии вашего острова, сохраняемые данные будут автоматически объединены в новой версии. Подробнее см. в разделе Изменение данных в опубликованных версиях острова.
Последствия отката опубликованного острова
Если вы откатите свой остров к предыдущей версии через творческий портал, сохраняемые данные для всех пользователей будут сброшены.
Уведомления игроков о том, что на их данные повлиял откат, не предусмотрены.
Это приведёт к потере последних обновлений данных игрока и даже в некоторых случаях к полному сбросу данных игрока. Это может случиться, даже если откат не включает внутренние изменения в логике, которые могли бы повлиять на сохраняемые данные.
Из-за воздействия на сохраняемые данные мы рекомендуем использовать функцию отката только в крайнем случае.
Ограничения
Далее приведены ограничения при работе с сохраняемыми данными в Verse.
Максимальный размер сохраняемого объекта
Существует ограничение на объём данных, которые могут быть сохранены в weak_map для каждого игрока.
Запись weak_map — это общее количество данных, связанных с одним элементом weak_map. Одна запись weak_map имеет максимальный размер данных 256 килобайт (КБ) на игрока.
При сохранении значения `weak_map` рассчитывается общий объём памяти, необходимый для сохранения данных.
Вот несколько примеров данных, которые могут приближаться к пределу в 256 КБ:
Приблизительно 24 000 значений типа
floatилиint.Примерно 200 000 символов текста. Это примерно 60 страниц текста в среднем романе.
Если вы попытаетесь сохранить данные размером более 256 КБ для записи игрока, сделать это не удастся, отобразится ошибка Verse среды выполнения.
Вы можете избежать ошибок сохранения, используя вспомогательную функцию Verse FitsInPlayerMap. Функция FitsInPlayerMap берёт копию записи, которую вы хотите сохранить, и проверяет её размер. Если запись может быть сохранена, вызов функции завершится успешно; в противном случае, если запись слишком большая, он завершится неудачей.
Функция FitsInPlayerMap особенно полезна, когда вы работаете с динамическим массивом или ассоциативным массивом данных и добавляете к ним новые элементы. Обновление int, float или logic, которые ранее были в сохраняемой записи, не изменит размер сохраняемой записи.
Максимальное количество слабых ассоциативных массивов игрока на остров
Один остров может иметь до четырех сохраняемых переменных, то есть четырех переменных weak_map с player в качестве типа ключа. Это требование обеспечивается компилятором Verse.
Требуемый слабый ассоциативный массив с типом класса
Значение weak_map как минимум одной сохраняемой переменной должно быть классом, если достигнут предел для максимального количества сохраняемых переменных. Это позволяет гарантировать, что в переменные позже можно будет добавить больше данных, обеспечивая при этом обратную совместимость при последующей публикации острова.