Постараюсь рассказать о том, как же на самом деле работает компьютерная игра. В одной из соседних тем я видел попытки одного человека предположить ее устройство, неверные, само собой.
Для начала представим, что у нас есть некая россыпь файлов. Файлы большие, внутри них находятся данные игры. Формат файлов известен. Начнем тему в формате QnA Вопрос-Ответ.
Вопрос: Как же получить доступ к модели персонажа A, лежащей в архиве B? Неужели этот архив необходимо разжать?
Ответ: А очень просто, и никакие архивы распаковывать для этого не надо. В произвольном месте архива (в каком именно - положено знать загрузчику файла) мы можем разместить своеобразную “карту” архива, где укажем, какие файлы содержатся внутри него, и в каком количестве, да какой они имеют объем. Само собой, все данные отделяются друг от друга отступами. Нам может потребоваться знать отступ от начала архива до модельки персонажа A и объем модельки. В большинстве случаев, модели легковесны, но об этом ниже. Таким образом, мы считываем из файла B по смещению Offset нашу модельку с объемом Len и записываем в буфер. Все, наша моделька прочтена, мы можем делать с ее данными все, что захотим.
Вопрос: Что будет, если мы все-таки станем разжимать архивы с игровыми данными прямо во время игры?
Ответ:
Ничего хорошего для производительности, поскольку алгоритмы, применяемые для упаковки\распаковки могут оказаться крайне ресурсоемкими, учитывая возможное количество данных внутри таких архивов. Распаковка данных станет очень заметна по снизившейся производительности и уменьшению места на диске (кто-то до сих пор игры ставит на системный раздел, и такой человек заметит распаковку данных игры моментально).
Вопрос: Сколько весит игровая модель и почему?
Ответ: Игровые модели, как я уже говорил выше, легковесны. Они могут быть представлены в виде одного файла, либо в виде нескольких. Допустим, у нас есть один файл A_ref и рядом A_anims. Это значит, что в первом файле лежит геометрия модели с различной технической информацией (например, список используемых материалов, которые мы в игре потом видим в виде наложенных на модель текстур с рельефом и светяшками-блестяшками различными), а во втором полный набор трансформаций, которые мы воспринимаем как анимацию, заставляющую персонажа двигаться. Анимации бывают вершинными и скелетными. Вершинная анимация требует больше памяти и используется, преимущественно, для анимации лиц в некоторых игровых движках. В основном, используется анимация скелетная. И та и та весят сравнительно немного, но об этом ниже. Для сравнения: модель в игре Heroes of the Storm может весить 2 мегабайта без учета текстур. То есть, это только ее геометрия и анимации. При желании, разработчик может оставить за собой возможность сжимать данные модели, в том числе геометрию и анимационные последовательности, и записывать их в бинарные файлы, но это уже тонкости реализации и у каждого разработчика свой подход к этому делу.
Вопрос: Сколько анимаций может быть у персонажа и сколько они весят?
Ответ:
В современной компьютерной игре у персонажа могут наличествовать десятки и сотни, если не тысячи различных анимаций. Анимационная последовательность весит немного, потому как она не включает в себя геометрию персонажа, к которой привязывается. В файле со скелетной анимацией находятся только данные о смещениях костей. Немного иначе ситуация обстоит с вершинной анимацией, где вопрос может решаться по-разному. Например, через те же текстуры, но чаще всего через промежуточные цели морфинга. Для морфинговой анимации лица нам необходимо заранее изменить расположение нужных вершин, чтобы получилось лицо произносящее определенную фонему или с улыбкой во все 32 зуба. Но и такая анимация обычно весит немного. Впрочем, для компьютерной игры важна производительность, а не детализация или плавность движений. Поэтому, кадров в анимационной последовательности персонажа, созданного для компьютерной игры, тоже может быть раз-два и обчелся.
Вопрос: Сколько весят текстуры в компьютерных играх и почему?
Ответ:
Столько, сколько захотите. Реализация зависит от подхода разработчика и от рамок, которые он ставит. Если требуется максимально высокое разрешение текстур, то весить они будут много, а если требуется поскромнее - то и результат выйдет соответствующим. Также, текстуру можно сгенерировать на этапе загрузки игры или уровня в произвольном разрешении, если заранее известен и написан подходящий для ее генерации алгоритм. Тут определенных каких-то ограничений нет. Разрешение текстур героев в HotS, если мне память не изменяет, составляет около 2048х2048 точек. При этом, текстуры окружения куда как скромнее. Текстуры для графического интерфейса пользователя - тоже. В большинстве файлов с текстурами игры хранится также информация об их уровнях детализации, в простонародье названных MIP. Это чтобы память экономить и производительность в игре не страдала, превращаясь в слайдшоу при каждом удобном случае.
Вопрос: А причем в компьютерных играх архитектуры центрального процессора?
Ответ:
Разработчик в праве компилировать свою программу под любую процессорную архитектуру, под которую у него есть подходящий компилятор. Компилируя проект под большее количество архитектур, разработчик охватывает большую аудиторию своего продукта. На самом примитивном уровне, компиляцию под ту или иную архитектуру означает банальную возможность запустить продукт под операционной системой, заточенной для использования с процессором такой-то архитектуры. 64-разрядная архитектура позволяет быстрее выполнять код, написанный для 32-разрядной архитектуры и оперирует числами большей длины, что позволяет повысить точность и скорость в сложных расчетах. Большинство игроков этого всего может просто не заметить, поскольку разработчики игр всегда стремятся достичь максимальной производительности, тогда как подобная точность важна для совершенно иных задач, которые рядовой пользователь перед своим компьютером даже не поставит. В играх точность расчетов никогда не является идеальной, и это обстоятельство позволяет повысить производительность в игре.
Вопрос: Чем в процессе игры занимается центральный процессор?
Ответ:
Центральный процессор во время игры играет (пардон за тавтологию) роль менеджера, выдающего всем вокруг себя задания. За заданиями к нему выстраивается очередь, и CPU ее призван контролировать, направляя в один или в несколько потоков. Но, в случае с несколькими потоками на него также ложится задача синхронизировать данные между ними. Например, в одном потоке у нас физика, а в другом графика, а в третьем звук. Предположим на простом примере, что нам нужен падающий мяч со смешным звуком. В потоке с физикой у нас есть физическая модель мяча - пресловутая коллизия в форме сферы. Во втором потоке у нас графическая модель мяча - сфера с текстурой и эффектами, висящая над землей. В третьем потоке у нас задача воспроизвести звук сразу, как только мяч приземлится. Без синхронизации мы получим, что физическая модель мяча упала и приземлилась, графическая модель мяча осталась висеть в воздухе, а звук прозвучал до падения. Это я еще утрирую, поскольку в реальности программа может просто упасть без выполнения, если не случится синхронизации. Синхронизация, как раз-таки, необходима для того, чтобы все случилось в свое время. Поэтому, процессор видит падение физической модели и передает ее текущие координаты модели графической, и та движется вместе с физической моделью. Далее, физическая модель сообщает процессору о своем столкновении с поверхностью, и тот уже дает команду третьему потоку воспроизвести звук. И все это производится в цикле, например - 60 раз в секунду, или чаще. Частота синхронизации может быть привязана к частоте кадров, а может и не быть привязана к ней. В зависимости от того, какую реализацию выбирает разработчик, так она и работает. Примерно так функционирует многопоточность в компьютерных играх, и появилась она еще до начала нулевых.
О чтении игровых данных
Когда мы говорим о доступе к игровым данным, мы можем поступить множеством различных путей. Например, мы можем единожды открыть для чтения архив или пак и не загружая его целиком в оперативную память загружать из него только нужные данные, руководствуясь его картой. Также мы можем, пользуясь все той же картой находить нужные нам данные и разжимать только их. При этом, файл архива\пака в память целиком не грузится, игра работает только с данными, лежащими на диске. Есть и другие пути добиться того же результата. А все, собственно говоря, почему? Раньше игры тоже были разными, очень разными и их данные могли занимать, скажем, 700 мегабайт пространства на жестком диске притом, что у пользователя, скажем, оперативной памяти было только 32 мегабайта а то и меньше. Если взять сегодня и распаковать все данные какой-нибудь игры того времени, мы можем получить в некоторых случаях около 2 гигабайт данных, и большую часть из них занимают текстуры, музыка, звуки, видео, лишь малая часть уходит на геометрические модели окружения, персонажей и так далее. Разумеется, компьютерная игра не располагала возможностями грузить в память сразу все данные, ведь для нее производительность стоит на первом месте. Чтобы ограничить расход памяти решили загружать только те данные, которые нужны на определенной карте в определенный момент времени. Ну и еще кучу других оптимизаций использовали вроде собственного менеджера памяти, отсечения невидимых игроку поверхностей и всякого такого. Ввиду необходимости разжимать данные, приходилось тщательно следить за расходом оперативной памяти, иметь собственный пул и всякое такое. Между уровнями частенько все ненужные данные из памяти подчищались, а на их место загружались новые. На компьютерах того времени по ряду причин, включая необходимость разжимать данные, загрузка того или иного уровня могла занимать приличное количество времени. Сегодня мы этого не замечаем, поскольку и скорость чтения жесткого диска стала выше и современные процессоры успевают провернуть все необходимые операции, включая тот же decode, намного быстрее. Также, спасибо надо сказать разработчикам библиотек вроде той же zlib за оптимизацию.
И также, исходя из этих и прочих знаний об алгоритмах компьютерных игр, я глубоко сомневаюсь, чтобы HotS, основанная на движке Starcraft II, вышедшей вот уже около 8 лет назад (а ее технологическая основа закладывалась и того раньше - как минимум, за несколько лет до выпуска игры и может основываться на переработанном коде движка Warcraft III вышедшего еще раньше) организовывала работу с медиа-контентом как-то иначе. Но, как показывает практика применения конечного продукта, а именно - игры HotS, она не выгружает данные ранее подгруженной карты из оперативной памяти, а держит там на случай, если они скоро потребуются вновь. И при этом она не выходит за рамки использования 4 гигабайт оперативной памяти, даже будучи запущенной в разрешении 4K.