Почему Star Citizen Ещё Не Вышел? - Часть 2.5. Создание Серверных Технологий
Когда мы готовили первые две части Почему Стар Ситизен еще не вышел, то потратили прорву времени выискивая факты и детали разработки проекта, о которых знали лишь единицы. Дневники разработчиков вроде воспоминаний Бена Лезника, или же давно забытые интервью Эрика Киерона Дейвиса или Шона Трейси, будучи на позиции консультанта для Звездного Гражданина от Крайтек, здорово помогли нам сложить картину технических и менеджерских сложностей игры. Как не странно, нам также помогли и хейтеры проекта, среди бреда которых мы все же смогли взять много фактической информации.
Тут же ситуация совершенно другая. В этом интервью, вышедшим некоторое время назад в журнале JumpPoint, разработчики очень детально расписали многолетний процесс создания OCS и все технические аспекты этому сопутствующие.
Перед вами перевод рассказа Кристофера Болта, главного программиста движка в Cloud Imperium, который участвовал во всех этапах разработки Object Container Streaming. Данный материал значительно дополняет наши первые две части и восполняет пробелы по техническим тонкостям разработки Звездного Гражданина, коих нам так не хватало создавая предыдущие видео. Именно поэтому данную часть мы промаркировали не иначе как “Часть два с половиной”.
Сперва мы расскажем, что такое Object Container Streaming. Затем затронем технологические ограничения, которые необходимо преодолеть на этом пути, а также кратко рассмотрим, как создаются такие большие и сложные программные технологии. После этого остановимся на отдельных частях и уже достигнутых промежуточных целях, ведущих к Object Container Streaming.
ЧТО ТАКОЕ OBJECT CONTAINER STREAMING
Прежде чем углубляться в технические детали, мы должны понять, что Object Container Streaming должен предоставить игрокам.
В кратце, Object Container Streaming - это собирательный термин для всех технологий, которые необходимы для создания огромной бесшовной вселенной, и благодаря которым становится возможным перемещение по чрезвычайно большому виртуальному миру без загрузочного экрана.
ТЕХНОЛОГИЧЕСКИЕ ВЫЗОВЫ НА ПУТИ К ОБЖЕКТ КОНТЕЙНЕР СТРИМИНГ
Но что подразумевает внедрение этой технологии для игрового движка? Прежде всего, видеоигра должна иметь частоту обновления экрана не менее 30 кадров в секунду, для поддержания плавности ощущений.
Чтобы достичь 30 кадров в секунду (FPS), игра должна выполнить все необходимые вычисления для каждого кадра в течение 0,033 секунды (33 миллисекунды). Несоблюдение этого временного ограничения приведет к подтормаживанию, так как ощущения плавного движения нарушаются при частоте ниже 30 кадров в секунду, и человеческий мозг начинает распознавать отдельные кадры.
ОГРАНИЧЕННАЯ ОЗУ И СКОРОСТЬ ПЕРЕДАЧИ ФАЙЛОВ
Более того, ПК имеет ограниченный объем «оперативной памяти» (ОЗУ). ОЗУ - это очень быстрая память, которая может передавать и архивировать 20 000 или более мегабайт в секунду (МБ/с). Чтобы обеспечить бесперебойную работу, необходимо, чтобы доступ ко всем необходимым данным осуществлялся внутри ОЗУ, а не на гораздо более медленном жестком диске.
Поскольку объем оперативной памяти ограничен и в разы меньше необходимого объема данных для бесшовного огромного мира, мы должны подгружать новые данные с жесткого диска и заменять ими другие ненужные данные прямо во время игры. Это требует времени. Передача всего 10 МБ с быстрого жесткого диска со скоростью 500 МБ/с требует 0,2 секунды загрузки, что составляет примерно 6 кадров при 30 кадрах в секунду, приводя, таким образом, к заметному притормаживанию.
Следовательно, все передачи файлов должны выполняться таким образом, чтобы не влиять на симуляцию мира во время игры, для обеспечения плавности при путешествии по бесшовной вселенной.
МНОГОПОТОЧНОЕ ВЫПОЛНЕНИЕ ПРОГРАММЫ
Это приводит нас к многопоточности. Каждый центральный процессор (ЦПУ) в последние 10 лет имеет несколько ядер. Каждое ядро ЦПУ может выполнять программные инструкции независимо друг от друга. Это (и другие методы, которые мы опускаем для облегчения понимания) позволяет компьютерам одновременно выполнять несколько задач. В случае Object Container Streaming мы можем загружать ресурсы параллельно игровой логике, что не влияет на частоту обновления кадров в игре.
Загрузка ресурса - это больше, чем просто время передачи файла. После загрузки с жесткого диска данные ресурса должны быть инициализированы - что может занять некоторое время и увеличить время до использования ресурса. Аналогичная проблема возникает когда ненужный ресурс нужно убрать, так как его необходимо сначала деинициализировать, что также требует времени.
Но худшая проблема - это обмен данными. В игровом движке есть несколько центральных программ для определенных типов ресурсов (таких как текстуры или персонажи). Эти программы обычно поддерживают список загруженных элементов ресурса своего типа и проводят с ними операции. Упрощенным примером будет менеджер персонажей, который ведет список всех загруженных персонажей. Каждый кадр, игровой симулятор просит менеджера персонажей обновить всех загруженных персонажей. И тут возникают сложности. Если загрузка нового персонажа заканчивается параллельно с обновлением перечня персонажей, программа попытается поместить недавно загруженного персонажа в список менеджера персонажей, чтобы данный персонаж начал получать пакеты обновления данных. Помещение персонажа в список изменяет его. Если игровой симулятор одновременно использует тот же список для отправки обновленных данных, это может привести к повреждению данных и крашу игры.
Таким образом, для корректного выполнения программы, только одна команда может одновременно обращаться к такому менеджеру. Другими словами, исполнение команд должно быть взаимно исключающим; если игровая симуляция использует менеджера какого-либо ресурса, загрузка данного ресурса должна подождать, и наоборот. А ожидание занимает время, которого у нас нет из-за ограничения по времени в 0,033 секунды, что подводит нас к основной сложности многопоточного программирования: поиску минимально необходимого времени для обмена данными, при котором программа все еще выполняется корректно. Если это не будет сделано правильно, игровая симуляция может ожидать передачи всего файла, что снова приведет к нежелательномому притормаживанию. Или игра просто время от времени будет крашиться из-за повреждения данных. Следовательно, весь технологический аппарат должен быть спроектирован с одновременной загрузкой, инициализацией и уничтожением ресурсов, сводя к минимуму обмен данными, чтобы не влиять на симуляцию игры.
ТЕПЕРЬ О РАЗРАБОТКЕ ОБЖЕКТ КОНТЕЙНЕР СТРИМИНГА В ОНЛАЙН ИГРЕ
Object Container Streaming находится в разработке уже несколько лет. Некоторые этапы его внедрения стали очень заметны для игроков, например Network Bind Culling, и другие, например, удаление Lua и доработка устаревшего кода.
Одним из основных препятствий на пути развития этой технологии стал тот факт, что Стар Ситизен является функционирующей онлайн игрой. Тут есть регулярные релизы.
Плюс постоянно разрабатывается новый функционал для создания игры. Из-за постоянной разработки и регулярных выпусков, разработчики не могут себе позволить, чтобы игра находилась в нерабочем состоянии в течение нескольких месяцев. В то же время, Object Container Streaming требует внесения изменений в фундаментальные законы, на основе которых разрабатывается игровой функционал. Поэтому для каждого шага, который предпринимается CIG, учитываются его влияние на график выпуска патчей и то, какие существующие функции необходимо будет переделать. Исходя из этого, нужно находить способы внесения изменений необходимых для Object Container Streaming таким образом, чтобы команды работающие над игрой постепенно адаптировались к этим новым законам, сохраняя при этом работоспособность игры.
КОНЦЕПЦИЯ КОНТЕЙНЕРОВ ОБЪЕКТОВ И ЧТО ЭТО ТАКОЕ.
Необходимо было выполнить несколько шагов, прежде чем CIG могли даже подумать о разработке Object Container Streaming. Примерно пять лет назад они начали внедрять концепцию Object Container. До этого движок поддерживал только «уровни». Уровень - это список игровых объектов. Сам игровой объект представляет собой набор ресурсов. Перед воспроизведением уровня все объекты должны быть загружены в ОЗУ с жесткого диска и инициализированы, что обычно происходит за экраном загрузки.
“Контейнеры Объектов” (с англ. - Object Containers”) являются строительными блоками уровня. Их концепция заключается в том, что вместо разработки одного большого уровня создатели контента разрабатывают небольшой раздел. Окончательный уровень (или вселенная в нашем случае) состоит из множества различных секций, или Контейнеров Объектов. Эта концепция позволяет CIG, во время создания уровня, разделить мир на множество более мелких строительных блоков.
Кроме того, построение потоковой передачи позволяет загружать и выгружать эти строительные блоки прямо во время игрового процесса, гарантируя, что разработчики вписываются в пределы ресурса ОЗУ, обеспечивая целостную вселенную. Хотя внедрение концепции Контейнеров Объектов не оказало заметного влияния на игроков (поскольку долгое время CIG просто загружали все контейнеры объектов во время загрузки уровня), она была важной ступенью к разработке будущих технологий.
Lua И ДРУГИЕ КОМПОНЕНТЫ
Работа над двумя другими требуемыми компонентами была начата около двух с половиной лет назад. Сначала разработчики предприняли удаление Lua из кода игры. Lua - это скриптовый язык программирования который интенсивно использовался для всех видов логики в движке. Проблема с Lua заключалась в том, что было невозможно сделать многопоточное выполнение программ безопасным. Другими словами, пока CIG использовали Lua, то не могли выполнять загрузку ресурсов параллельно с симуляцией игры. Следовательно, они были вынуждены заменить весь код Lua на C ++, что позволило значительно сократить время ожидания при загрузке.
В то же время девы начали преобразовывать свои игровые объекты из более крупных монолитных в отдельные компоненты. Компонент объекта отвечает за часть определенного игрового поведения. Благодаря компонентам, поведение объекта определяется типами компонентов, из которых он состоит. Без компонентов все виды различной логики поведения чередовались бы в одном монолитном и очень сложном центральном логическом блоке.
Использование компонентов позволило сделать несколько улучшений в реализации игровой симуляции. Поскольку они являются небольшими частями, гораздо проще заставить их эффективно взаимодействовать с игровым симулятором, в то время как этот движок загружает их одновременно. Кроме того, они разделили логику монолитной игры на более управляемые отдельные части, что сыграло решающую роль в частичном внедрении параллельной инициализации объектов.
СЕРИАЛИЗАЦИЯ ДАННЫХ
Объекты внутри игрового симулятора имеют определенное состояние. В некоторых ситуациях, таких как сетевое взаимодействие, CIG вынуждены хранить это состояние в формате, который возможно передать и восстановить в том же виде на другом компьютере. В других ситуациях, таких как сохранение прогресса в Squadron 42, требуется что-то подобное, за исключением той разницы, что данные сохраняться на жестком диске. На языке программистов, процесс преобразования состояния объекта в формат, который может быть сохранен на диске или передан по сети, называется «сериализацией». Отсюда и название “сериализация данных”. Это концепция, в которой берутся части объекта и помещаются в специальный формат называемый пакетом данных. Такие пакеты данных позволяют сериализовать состояние объекта.
Таким образом, CIG могут писать игровой код в едином стиле, независимо от того, как будут передаваться сериализованные данные позже (это также важно для Server Meshing, как мы выясним далее).
МНОГОПОТОЧНАЯ ЗАГРУЗКА РЕСУРСОВ ДВИЖКА
Помимо ресурсов, связанных с игрой (составляющих данные), движок также поддерживает множество общих ресурсов, которые совместно используются разными компонентами и даже разными Контейнерами Объектов. Эти ресурсы включают такие объекты, как текстуры или полигональные сетки. Движок уже поддерживает потоковую передачу полигональных сеток и текстур, которая представляет собой процесс загрузки и выгрузки данных графического процессора для рендеринга во время игры. Но для Object Container Streaming было необходимо воплотить это на более высоком уровне.
В контексте OCS было важно загружать объект из данных графического процессора параллельно и упорядочено, чтобы все параллельно загруженные Контейнеры Объектов могли использовать одни и те же общие ресурсы движка. Работа над этой технологией продолжается в фоновом режиме уже около двух с половиной лет.
ИТОГИ ПОДГОТОВИТЕЛЬНЫХ РАБОТ
Основные подготовительные работы, описанные выше, потребовали больших трудозатрат, и большинство из них было невидимо для игроков, поскольку внесение этих изменений без видимого эффекта и было целью разработчиков, в основном дабы убедиться, что изменения были внесены корректно. Но все это было очень необходимой работой, которая вывела технологию игры на новый уровень и привела к первым заметным продвижениям, когда Обязующее Сетевое Отсечение или Network Bind Culling увидело релиз в Alpha 3.3.
ПАРАЛЛЕЛЬНАЯ КОМПОНЕНТНАЯ ЗАГРУЗКА И ИНИЦИАЛИЗАЦИЯ
С завершением подготовительных работ разработчики получили:
- • Уровни разбитые на строительные блоки (Контейнеры Объектов)
- • Объекты (которые составляют большую часть Контейнеров Объектов) реализованы без Lua и разбиты на отдельные компоненты
- • Все состояния объектов сериализуются в пакеты данных для облегчения обмена данными через сеть
- • Многопоточное создание ресурсов движком (текстур, полигональных сеток, персонажей и т. д.)
Следующие шаги создавались на основе этого фундамента. Первой целью было научиться подгружать новые объекты одновременно с симуляцией игры. Этот первый шаг не включал в себя высокоуровневую логику того, что и когда подгружать или выгружать, так как это была очень упрощенная первая стриминговая система. Тем не менее, это уже уменьшило подвисания во время игры. Например, вызов корабля больше не требовал запуска кода инициализации объектов корабля в ущерб симуляции самой игры.
На тот момент у нас было примерно от 300-от до 400-от различных типов компонентов. Если бы CIG попытались выполнить все это одновременно с самого начала, они бы утонули в багах. Поэтому им пришлось разработать систему, позволяющую постепенно обрабатывать все больше и больше типов компонентов параллельно с симуляцией игры. Чем больше типов компонентов удасться безопасно (с точки зрения крашей) обрабатывать параллельно, тем меньше будет подвисать симулятор игры.
Решение, которое нашли разработчики, это использование Волокон. Волокно в программировании - это состояние выполнения потока, в котором можно точно контролировать, когда и где его необходимо выполнить - в параллельной загрузке или в симуляции игры. Хотя волокна могут быть очень сложными в использовании, они обеспечивают именно тот контроль, который был нужен CIG.
С помощью волокон они смогли переключать логику загрузки ресурсов между потоками одновременной загрузки и потоками симуляции игры, в зависимости от того, поддерживает ли данный тип компонента параллельную загрузку или нет. И с этим стало возможным пошагово настраивать все больше и больше кода игры для многопоточного одновременного выполнения, при этом обеспечивая использование и, следовательно тестирование, такого параллельного выполнения кода игроками. Эти изменения были частично имплементированы в Alpha 3.2, что позволило уменьшить подвисания, вызванные загрузкой ресурсов объектов во время симуляции игры, например, при вызове кораблей.
ПОДГОТОВКА К ОБЯЗУЮЩЕМУ СЕТЕВОМУ ОТСЕЧЕНИЮ
Обязующее Сетевое Отсечение - это то, как Object Контейнер Streaming реализуется со стороны клиента. Другими словами, это процесс принятия решения о загрузке / выгрузке тех или иных объектов на любом клиенте. CIG решили сосредоточиться в первую очередь только на клиенте, поскольку это позволило внести ряд улучшений игрокам, обеспечило последовательное развитие технологии и решило некоторые проблемы на следующих этапах (которые описаны в разделе Server Object Container Streaming). Но даже сосредоточившись только на клиенте, им пришлось проделать большую подготовительную работу.
ПРОГРАММА ОБНОВЛЕНИЯ КОМПОНЕНТОВ ОБЪЕКТОВ
CIG планируют решать какие объекты загружать или выгружать на клиенте, основываясь на расстоянии и видимости этого объекта с точки зрения клиента. Поэтому им нужна эта информация. К счастью, они уже разработали такую технологию для Alpha 3.0. Программа Обновления Компонентов Объектов - это система, предназначенная для управления обновлением компонентов объекта в зависимости от их пространственного расположения относительно игрока. Таким образом, разработчики могут избежать обновления компонентов, которые находятся слишком далеко. Еще одно преимущество разбивки на компоненты состоит в том, что так можно обновлять каждый компонент в отдельности. Само собой, Программа Обновления Компонентов Объектов должна предоставлять ту же информацию для Обязующего Сетевого Отсечения.
ИЕРАРХИЯ СОБСТВЕННОСТИ ОБЪЕКТОВ И СОВОКУПНОСТЬ ОБЪЕКТОВ
Еще одна важная проблема с которой разработчикам пришлось справиться это динамические группы объектов. Во время дизайна, Контейнеры Объектов разбивают статическую геометрию уровня и объекты на строительные блоки. Но в игре также присутствуют динамические объекты, такие как игроки и корабли, которые сами могут состоять из нескольких Контейнеров Объектов - в общем все то, что может перемещаться в виртуальном мире. Кроме того, эти динамические объекты могут объединяться в группы. Например, игрок поднимает объект или корабль стыкуется с другим кораблем. Это имеет некоторые последствия для потоковой передачи. В ситуации когда один корабль находится внутри другого, не нужно передавать состояние первого корабля до передачи состояния корабля в котором он находится, поскольку состояние одного частично определяется вторым. Поэтому CIG должны отслеживать такие динамические группы когда они формируются или расформировываются. Эту концепцию разработчики назвали Иерархией Собственности Объектов. При помощи этой иерархии отслеживаются объекты, которые связаны друг с другом. Если объекты связаны, их расценивают как одну группу - так называемую Совокупность Объектов.
Опираясь на это, Обязующее Сетевое Отсечение работает с Совокупностями Объектов, используя информацию поступающую от Программы Обновления Компонентов Объектов для определения, того какие Совокупности Объектов загружать или выгружать на каждом клиенте.
ГРУППЫ ВЫЗЫВАЕМЫХ ОБЪЕКТОВ
После распознания Совокупности Объектов все еще нужно было разработать способ эффективного появления (спауна) большого количества объектов внутри Совокупности Объектов. Так же нужно обеспечить, чтобы Объекты появлялись на клиентах упорядоченным образом, чтобы у клиента возникала та же Совокупность Объектов и Иерархия Объектов, что и на сервере. Это необходимо, например, чтобы корабли появлялись сразу с оружием / двигателями, а не так чтоб компоненты появлялись постепенно после появления корабля. Чтобы достичь этого, CIG группируют объекты в Группы-Вызываемых-Объектов, что представляют собой наборы объектов, которые должны появиться вместе и становиться активными только после того, как все компоненты прогрузились.
Для каждого объекта, который появляется на клиентском компьютере, отправляется что-то вроде “снимка” объекта с сервера, содержащий текущее состояние объекта. Это просто значения Сериализованных-Переменных, принадлежащих объекту. Снимки также используются для сериализации состояния объектов для обеспечения постоянства или для сохранения в Squadron 42. Поскольку создание объектов асинхронно на клиенте и требует времени, проблема, с которой столкнулись CIG, заключалась в том, что к тому времени, когда клиент завершил загрузку Группы-Вызываемых-Объектов, снимок объекта мог уже устареть, поскольку состояние объекта на сервере могло измениться, пока клиент его загружал.
Чтобы это исправить, сервер должен отправить второй набор снимков объектов, как только клиент загрузит всю Группу Вызываемых Объектов. При получении вторичных снимков объектов, выполняется незначительное исправление состояния объектов и, наконец, добавление их в симуляцию клиента.
ОТСЕЧЕНИЕ СЕРИАЛИЗОВАННЫХ ДАННЫХ
С выпуском Alpha 3.0 многое уже было разработано. CIG также представили планеты и многие крупные локации, такие как Levski и Grim HEX. Тем не менее, не все необходимые детали были завершены.
В то же время было готово только обновление отсечения Программы Компонентов Объектов. Хотя эта система помогла с производительностью сервера, клиентам все равно приходилось сталкиваться с излишними нагрузками, ведь в то время у CIG еще не было системы, для точного определения информации требуемой для каждого клиента. Кроме того, каждый компонент должен был обновляться при получении новой сетевой информации, что приводило к существенным проблемам с производительностью. Например, если Игрок А находился на Levski, а Игрок Б на Olisar, то Игрок Б получал обновления по всем NPC на Levski, поскольку Игрок А находился рядом с ними на сервере. Но уже были готовы инструменты, с помощью которых можно было отсечь только необходимую информацию. Поэтому разработчики решили создать систему, которая отправляла бы сетевые обновления клиентам только в том случае, если этот клиент находится в непосредственной близости от определенной Группы Объектов. Итак, в предыдущем примере, игрок B больше не будет получать обновления по NPC на Levski, так как сервер будет знать, что игрок B не находится поблизости.
Реализация подхода Отсечения Сериализованных Данных дала заметное улучшение производительности клиентов. Кроме того, это был первый реальный тест запуска клиентского игрового симулятора с использованием только частичной информации о всей вселенной. CIG хотели внедрить эту функцию с Alpha 3.0, но вопреки всем усилиям сетевой команды, смогли ее реализовать только в Alpha 3.1.
ОБЕСПЕЧЕНИЕ ОБЯЗУЮЩЕГО СЕТЕВОГО ОТСЕЧЕНИЯ
Итак, спустя несколько лет после того, как были предприняты первые шаги и выпущено несколько версий игры, мы можем наблюдать результаты этой работы. На данный момент у CIG имеются следующие достижения:
- • Уровни разбиваются на строительные блоки (Контейнеры Объектов)
- • Объекты (которые составляют большую часть Контейнеров Объектов) реализованы без Lua и сегментированы на компоненты
- • Все возможные состояния объекта форматируются в сериализованные данные для облегчения обмена ими через сеть
- • Многопоточное создание ресурсов движка (текстуры, полигональные сетки, персонажи и т. д.)
- • Многопоточное создание большинства типов компонентов
- • Информация о близости между всеми объектами и игроками предоставляется Программой Обновления Компонентов Объектов
- • Осуществлена возможность отслеживать динамические группы объектов
- • Разработан эффективный способ вызова Групп Объектов клиентом
- • Первое практическое использование Отсечения Сериализованных Данных для игровой симуляции на клиентах.
Используя все вышеописанные достижения, разработчики смогли наконец разработать Обязующее Сетевое Отсечение. Данная технология позволяет вместо упущения сетевых обновлений при наличии всех объектов на каждом клиенте, как это было при Отсечении Сериализованных Данных), загружать и выгружать объекты на клиенте под руководством сервера. Другими словами, Обязующее Сетевое Отсечение позволило клиентам загружать лишь определенную видимую часть гораздо большего виртуального игрового мира, в то время как при Отсечении Сериализованных Данных каждый клиент хранил полную информацию об игровом мире, но выполнял лишь частичные обновления своего локального виртуального мира.
Это дает несколько преимуществ, наиболее заметным из которых является производительность. Каждый клиент теперь хранит гораздо меньший набор данных, что позволяет каждой локальной операции зависящей от количества объектов выполняться быстрее. Это также помогает с другими времязатратными процессами, которые не могут быть отсечены с помощью Отсечении Сериализованных Данных. Еще одним преимуществом является то, что клиент использует меньше памяти, так как ему нужно сохранять только поле своей видимости в оперативной памяти, а не всю вселенную. У многих клиентов наблюдалось значительное улучшение производительности, когда CIG внедрили Обязующее Сетевое Отсечение в Alpha 3.3.
Но у системы есть еще одно, еще более важное преимущество: она отделяет клиента от контента вселенной. Поскольку каждый клиент загружает только небольшой набор объектов, необходимых для его локального поля зрения, производительность клиентов больше не зависит от количества объектов, которые помещаются во вселенную. На производительность клиента теперь влияет только фактическое местонахождение клиента и его окружение (например, пустое космическое пространство или переполненный город). И это дает свободу размещать столько контента, сколько нужно в виртуальном мире, не беспокоясь о производительности клиентов.
Однако, на данный момент, сервер все еще должен иметь загруженной всю вселенную, что влияет на его производительность. И хотя плохая производительность сервера не влияет на частоту кадров клиентов, она вызывает рывки при перемещении объектов, так как весьма вероятно, что клиент и сервер не согласятся с положением того или иного конкретного объекта. Это очень серьезная проблема, которую CIG планируют решить с помощью Server Object Container Streaming или SOCS.
РАЗРАБОТКА SOCS
С внедрением Обязующего Сетевого Отсечения фокус сместился на реализацию Object Container Streaming на сервере (в переводе - Серверная Потоковая Передача Объектных Контейнеров).
Основная концепция заключается в том, что если рядом с объектом нет игроков, то можно будто бы «заморозить» состояние этого объекта. И вместо того, чтобы хранить замороженные объекты в памяти (в ущерб производительности), можно сериализовать их состояние и сохранить его в базе данных. Пока клиент перемещается по виртуальному миру, сервер обновляет хранящуюся на нем информацию из базы данных, загружая объекты, находящиеся теперь в непосредственной близости, а также убирая и перенося в базу данных более ненужные объекты.
Здесь Server Object Container Streaming и Network Bind Culling идут рука об руку. Идея такова - База данных содержит всю вселенную в замороженном состоянии. На сервере загружено только небольшое подмножество вселенной; другими словами, большая часть вселенной хранится в базе данных. Клиент также хранит только подмножество всех загруженных сервером объектов, находящихся в поле зрения клиента в виртуальном мире сервера. При этой модели система держат все объекты вдали от игроков в замороженном состоянии, чтобы эти объекты не влияли на производительность или память. Модель также имеет некоторые исключения, такие как Категоризация Моделирования Вселенной, но они выходят за рамки данного рассказа.
Когда Server Object Container Streaming будет завершен и всецело реализован, у CIG будет технологическое решение для масштабирования контента на сервере. Это означает, что они смогут разместить гораздо больше контента в виртуальном мире, в то время как на производительность сервера будут влиять только те области, где есть активные игроки, что намного меньше, чем весь мир. Но разработка Server Object Container Streaming сопряжена с определенными проблемами, над которыми в данный момент работают соответствующие команды, чтобы решить их как можно скорее.
ТЕКУЩЕЕ СОСТОЯНИЕ
Благодаря Обязующему Сетевому Отсечению, в системе сохраняется корректная версия каждого объекта, загруженного на сервер. Это позволило воплотить некоторые «ленивые» решения, поскольку CIG смогли избегать мелких проблем, исправляя их после загрузки объекта на клиент.
Одним из примеров этого является телепортирование игрока. Телепортация - это мгновенное перемещение из одного места в другое во вселенной. Это наихудший случай для потоковой передачи, но в игре это происходит в некоторых ситуациях, таких как респаун игрока. После телепортации все вокруг игрока должно быть загружено.
У CIG не было никакого приоритетного порядка, в котором бы загружались объекты. Это привело к тому, что NPC проваливались через еще не загруженный пол. С Обязующим Сетевым Отсечением это было не страшно, так как положение объектов зависело от сервера, отправляющего клиентам правильное местонахождение NPC - ведь на сервере пол всегда находился на месте.
Но с Server Object Container Streaming такого допустить нельзя. Поскольку сервер является основной инстанцией хранилища состояния объектов во вселенной, если NPC провалятся сквозь пол на сервере, они исчезнут и на всех клиентах, что приведет к пустым безлюдным городам. Поэтому CIG должны были обеспечить, чтобы пол всегда загружался до NPC. Другая проблема - это типы компонентов, которые хранятся только на сервере. Так как они будут храниться в базе данных до необходимости их появления, необходимо убедиться, что их состояние корректно восстанавливается из сериализованных данных.
Эти и другие мелкие проблемы - это то, что разработчики должны исправить, прежде чем внедрить Server Object Container Streaming.
МЕНЕДЖЕР ПОТОКОВОЙ ПЕРЕДАЧИ ОБЪЕКТОВ / STARHASH (СТАРХЭШ) / STARHASH RADIXTREE (СТАРХЭШ-РАДИКСТРИ)
Другая проблема возникает, когда выгружаются все объекты и сохраняются в базе данных. CIG нужен способ выполнять поиск среди сохраненных объектов по их пространственному расположению, чтобы загружать те объекты, которые находятся рядом с клиентами во вселенной. Поэтому было необходимо разработать схему поиска, которая позволила бы хранить огромное количество объектов с достаточной информацией о их пространственном расположении. Для этого разработчики адаптировали алгоритм Geohash (используемый всеми картографическими приложениями для поиска мест вокруг пользователей) для своих нужд, сделав его трехмерным и расширив его (наш виртуальный мир имеет больше возможных мест расположения, чем есть на реальной Земле). Назвали его StarHash.
StarHash стал эффективным инструментом для хранения объектов, обеспечивая быстрый поиск объектов в нужной области пространства, используя структуру данных, называемую RadixTree. Менеджер Потоковой Передачи Объектов, затем логически управляет запросами StarHash-RadixTree, чтобы инициировать загрузку и выгрузку объектов на сервере, основываясь на позициях всех подключенных клиентов.
ИДЕНТИФИКАЦИЯ РАСПОЛОЖЕНИЯ
Последняя важная проблема, с которой пришлось столкнуться CIG, - места появления игроков. Чтобы вызвать игрока, игровая логика требует Spawn-Point (точка возрождения), которая также является объектом. Но разработчики старательно шли к тому, чтобы загружать объекты, только если игрок находится рядом, поэтому игрок необходим, чтобы загрузить Spawn-Point для вызова игрока. Учитывая что Spawn-Points также невозможно исключить из потоковой передачи (так как они являются частью других более крупных конструкций, таких как космические станции), CIG пришлось найти другое решение.
Они решили эту проблему путем двухфазного процесса появления игрока. Когда игрок подключается, сначала система находит его Spawn Location-ID (идентифицируя его место появления). Местоположение - это концепция точки в пространстве. Таким образом, сначала загружаются все объекты в этой области, что также загрузит требуемую Spawn-Point. После этого игрок может безопасно появится в необходимой локации. Наконец, логика потоковой передачи переключится с Spawn Location-ID на игрока, чтобы обновление базы данных объектов вблизи этого игрока перемещалось вместе с ним.
ТЕКУЩАЯ РАБОТА
На момент нашего рассказа не все работы над Server Object Container Streaming еще закончены. CIG реализовали Менеджер Потоковой Передачи Объектов, а также логику StarHash. Работа с идентификатором местоположения почти завершена и должна быть завершена в ближайшее время. Из-за этого Server Object Container Streaming уже может использоваться в определенной степени. Его использование показывает все проблемы и места, которые еще предстоит исправить разработчикам и, те активно над ними работают.
Тем не менее, первая версия SOCS, вышедшая в январе 2020го уже обеспечила лучшее масштабирование контента на сервере, позволив добавлять множество таких сверх объемных ассетов как орбитальные станции и планеты с выросшим на несколько порядков уровнем детализации, который еще несколько месяцев назад был бы просто недостижим.
ПОСТОЯНСТВО МЕЖДУ ИГРОВЫМИ СЕССИЯМИ
Server Object Container Streaming не влияет на то, как и какие данные сериализуются для сохранения. Сейчас объекты хранятся в замороженном состоянии в незавершенной базе данных. Это означает, что состояние теряется при краше или перезапуске сервера (кроме того состояния, которое система уже сохранила как постоянное). Следующим шагом должна быть разработка эффективного доступа к сети, чтобы позволить сохранение объекта в базе данных на другом компьютере. Когда CIG реализуют этот шаг, состояние объектов будет сохраняться после перезапусков и крашей сервера (пока разработчики не удалят базу данных постоянства), продвигая игру к полномасштабному постоянству.
SERVER MESHING
При использовании Server Object Container Streaming один сервер отвечает за управление базы данных объектов в поле видимости всех клиентов. Таким образом, хотя Server Object Container Streaming должен улучшить производительность сервера (поскольку система загружает меньше объектов), в конечном итоге он не решит проблему большего числа игроков на сервер.
Вот тут-то в игру и вступает Server Meshing. В этой концепции, вместо того, чтобы один сервер управлял областями обзора всех игроков, области обзора отдельных игроков будут распределяться по нескольким серверам. Это снизит нагрузку на каждый участвующий сервер. Затем, когда CIG разместят эти сервера на разных машинах, то получат хороший и практичный способ распределения нагрузки с учетом количества игроков. Для реализации Server Meshing разработчики будут опираться на то, что уже используется прямо сейчас: объекты будут перемещаться между серверами с использованием сериализации данных, а также с учетом особенностей кода Server Object Container Streaming, для того чтобы правильно восстановить эти перемещенные объекты на другом сервере.
ПОДДЕРЖКА ГЕЙМ РЕДАКТОРА
Более скрытый от публики, но также очень важным является гейм Редактор. Редактор - это специальный инструмент движка, который используется для создания Контейнеров Объектов и размещения их во вселенной. Он также используется для тестового воспроизведения нового разработанного контента во время работы над ним, что крайне важно для контента высокого качества. К сожалению, сам редактор еще не поддерживает потоковую передачу. Таким образом, создатель контента может создавать и разрабатывать контент, но страдает при этом от длительного времени загрузки и низкой частоты обновления кадров. Эта проблема будет усугубляться по мере того, как больше контента будет добавляться в игру.
Поэтому следующий шаг очень важен - сделать Редактор потоковым и дать создателям контента те же преимущества, которые CIG дали клиентам (через Обязующее Сетевое Отсечение) и серверу (через Server Object Container Streaming). Но поскольку у Редактора есть своя дополнительная логика поверх всей игровой симуляции, разработчики смогут заняться этим только после полной имплементации Server Object Container Streaming.
ПОДДЕРЖКА SQUADRON 42
42я Эскадрилья станет самой легкой дополнительной работой. В Squadron 42 клиент также будет и сервером. Поэтому CIG просто применят тот же код, что и на сервере Star Citizen. На самом деле, они уже делают это. А поскольку Squadron 42 и Star Citizen совместно используют одну и ту же базу кода, исправления для Server Object Container Streaming для одного продукта принесут пользу и другому.
Подведем итоги
Приведенная выше информация, со слов Кристофера Болта, должна была дать объяснение многолетнему путешествию «Object Container Streaming» и понятно разъяснить основные технических проблемы, с которыми пришлось столкнуться и преодолеть разработчикам Звездного Гражданина в этом путешествии.
По заверению Кристофера, большинство технических деталей он умышленно упустил, иначе его рассказ разросся бы до объема целой книги. Мы же, со своей стороны, в очередной раз можем убедиться насколько сложным является процесс создания нового игрового продукта на основе новейших технологий, которые также приходится создавать с чистого листа параллельно с самой игрой. А ведь разработка технологии OCS это в лучшем случае одна десятая часть технических сложностей и преград на пути разработчиков к воплощению мечты под названием Star Citizen.