Дневник разработчиков Crusader Kings 3 #36

Cмотреть полную версию

Производительность

Начнем с производительности.
В процессе работы на CK2 мы привнесли в игру ряд улучшений производительности, и к моменту выхода Holy Fury она была на пике. Релизная версия сегодня кажется заторможенной улиткой по сравнению с тем, как ведёт себя игра в конце долгой и почтенной жизни.
CK2 в плане производительности выделялась среди прочих игр студии, и нам приходилось соответствовать.Поэтому в процессе разработки CK3 производительность всегда была для нас на первом месте, особенно сейчас, когда близится релиз. Ради производительности нам пришлось изменить свой подход к ряду технических систем по сравнению с тем, как это было в CK2, и это привело к поразительным результатам.

Сильнее всего ради проиводительности нам пришлось переделать две системы: многопоточности и рендеринга. Они сильно зависят друг от друга, так что не получится рассказывать об одной и не коснуться второй.
В CK2 мы придерживались довольно простого подхода. Игра в целом выстраивалась вокруг одного потока.Основной задачей главного потока было обновлять состояние игры с течением времени. Для создания кадров, позволяющих пользователю видеть, что происходит в игре, поток периодически прекращал обновлять состояние игры и вместо этого создавал кадр. Процесс рендера занимал всё время, пока кадр не будет создан.
Во время обновления состояния игры поток производил большое количество разнообразных операций. В CK2 структура этого процесса в основном была сосредоточена вокруг персонажей. Ежедневные обновления персонажей делились на несколько сегментов с различными правилами параллельной обработки. Например, во время одной из частей персонаж не мог проверять данные другого персонажа. Подобные ограничения позволяли проводить обновления параллельно, — каждый поток работал над одной и той же секцией для различных персонажей. На практике это работало довольно неплохо. CK2 в значительной степени опиралась на параллельную обработку данных и значительно выигрывала от этого. Подобный подход применялся и к другим объектам: титулам, заговорам и т.д.
Но были и существенные недостатки. Главный из них заключался в обилии правил, ограничивающих, что программист может и не может делать в каждом обновлении. Нарушение одного из этих правил зачастую приводило к рассинхронизации и ломало мультиплеер. А порой приводило к вылетам игры. Кроме того, необходимость проверки каждого персонажа приводила к неоправданному расходованию ресурсов, поскольку большинство проверок приводило к результату «нам нет нужны делать эту часть обновления».

Поэтому в CK3 мы полностью заменили эту систему. Мы перешли от параллелей на уровне объектов к параллелям на уровне системы. И вместо того, чтобы одновременно обрабатывать несколько персонажей, мы обрабатываем несколько различных систем. Например, мы можем одновременно обновлять систему происков и мнения. Это позволило нам значительно упростить правила касательно того, что можно делать, а что нельзя. Теперь в процессе распараллеливания мы ограничены лишь тем, что не можем менять видимую информацию. Вместо этого, нужно сохранять изменения, которые мы хотим осуществить, а затем чуть позже применить их все. Упрощение правил означает, что в игре будет меньше ошибок, в особенности рассинхронов. И зачастую куда проще понять, что можно распараллелить, по сравнению с CK2. В результате, в параллели можно осуществлять куда больше процессов, чем раньше.

Более того, это отлично работает в сочетании с новым подходом CK3 к рендерингу. Тут он сделан отдельным потоком, а не как часть основного. Ему всё ещё требуется постоянно синхронизироваться с основным потоком, поскольку мы не можем проверять объект в процессе изменения. Для этого у нас существует ряд ограничений. Когда потоку рендеринга нужно получить доступ к состоянию игры, оно не может менять себя, а когда состояние игры изменяется, потоку рендеринга нужно дождаться окончания изменения. Как и в CK2, состояние игры будет в процессе обновления периодически проверять, нужен ли доступ рендеру. И если да, то он на время передаст контроль. Но главное отличие в том, что для большей части работы потоку рендера не требуется доступ к состоянию игры, а потому его можно осуществлять параллельно обновлению состояния игры.
Помните правило, о котором я говорил выше? Параллельные обновления состояния игры не могут менять видимые состояния, так что в процессе этих обновлений можно спокойно обновлять поток рендера. Поэтому в целом время ожидания потока рендера довольно маленькое, и большую часть работы он производит одновременно с состоянием игры.
Однако, у нас всё ещё осталось распараллеливание на уровне объектов, в частности, ИИ. Но ИИ в CK3 настроен так, что не может напрямую изменять состояние игры, поэтому рендер может продолжаться, пока ИИ думает, что ему делать.

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

Я решил сравнить CK2 и CK3 и устроил небольшой тест на своём компьютере. Просто на минуту запустил игру на полной скорости, а затем сравнил частоту кадров и прогресс игры. Обе игры продвинулись одинаково далеко. Я начал в сентябре 1066 года, и обе они дошли до апреля 1069 года. Однако, частота кадров в CK3 была куда выше и стабильнее, чем в CK2. Учитывая куда лучшую графику в CK3, эти результаты — как раз то, на что я надеялся.

Давайте посмотрим, насколько сильно влияют потоки. Я на 1 минуту запустил игру на своём компьютере на максимальной скорости, сначала с включённым распараллеливанием потоков, а затем с выключенным. Ниже вы можете всё увидеть своими глазами. Слева с потоками, справа без них:

Видео загружается...

Итак, как же мы работаем с производительностью в CK3, помимо всего вышесказанного? Мы иногда выделяем время, чтобы разобраться с новыми проблемами производительности, а также ищем пути для дальнейшего улучшения. Зачастую это выливается в добавление новых потоков или изменение систем ради большей производительности. Но один из моих любимых способов увеличить скорость заключается в том, чтобы слегка модифицировать дизайн и избежать затратных расчётов, которые всё равно не повлияют на игрока. Например, мы ежедневно обновляем прогресс выполнения заданий советниками игрока. Но для ИИ делаем это раз в месяц. Игрок вряд ли заметит разницу, а мы таким образом снизили стоимость этих обновлений до 1/30 от возможных расходов ресурсов системы. Подобную оптимизацию в CK3 можно встретить повсеместно (и дажеCK2). Есть множество лазеек, которыми можно воспользоваться, чтобы значительно улучшить производительность, но которые почти не повлияют на игровой опыт.

ИИ

Теперь пора поговорить об ИИ.
На протяжении большей части работы над CK3 за ИИ отвечал Никлас «Captain Gars» Штрид, но сейчас он в отпуске по уходу за ребёнком. На протяжении примерно года я помогал работать над ИИ, а потому в его отсутствие вся ответственность за ИИ легла на мои плечи.
Поскольку не я разрабатывал ИИ, этот раздел будет короче, чем он мог бы быть, если бы его писал Никлас. Но я расскажу основные идеи, на которые мы опирались при работе над ИИ в CK3.

Основной целью перед ИИ мы поставили сделать игру веселее для игрока. Она состоит из нескольких частей:

  • ИИ должен создавать сложности, потому что сразу раскидывать врагов направо и налево не весело
  • ИИ должен избегать бесить игрока, даже если это сделает ИИ «умнее»
  • ИИ должен ощущаться как правдоподобный персонаж средневекового мира

Это цели одновременно и пересекаются, и противоречат друг другу. Например, если ИИ будет стараться меньше бесить, он станет создавать меньше сложности, но такие жертвы часто имеют смысл.

Одно из самых больших изменений в ИИ СК3 — это как он обращается с армиями. В СК2, если на одной стороне в войне было несколько ИИ, они действовали независимо с какими-то системами координации. В большинстве случаев это работало неплохо, но иногда из-за этого ИИ действовали неслаженно и принимали странные решения.
В СК3 мы с нуля создали систему, которая будет управлять несколькими ИИ на одной стороне. Вместо того, чтобы самим распоряжаться своими войсками, они передают в ведение координатора, который и принимает все решения. Сами ИИ решают только то, управление какими войсками передать (это становится нужно, когда они участвуют сразу в нескольких войнах).
Таким образом ИИ работает гораздо более слаженно.
Но это не помогает координироваться с игроком. В СК2 мы в итоге пришли к системе приказов для ИИ, когда вы просто сообщали ему, что нужно делать. В СК3 такой у нас пока нет, но ИИ всё ещё будет стараться помогать игроку. В основном он будет держать свои армии как можно ближе к игроку, и поможет в сражениях, даже если они всё равно будут проиграны. Система приказов для ИИ, конечно, могла бы всё это улучшить, но её влияние оказалось бы далеко не таким, как в СК2, поэтому до релиза мы решили отдать приоритет другим задачам. Кроме того, наличие системы приказов в СК2 значительно усложняет код ИИ, затрудняя дальнейшее его развитие, так что мы должны были учесть возможные побочные эффекты в виде кучи багов и замедления разработки ИИ.

Ладно, это было про «создание сложности», но что насчёт того, чтоб ИИ не бесил? С этой целью у нас сделано много мелочей тут и там, но давайте я расскажу о паре конкретных примеров. В СК3 у ИИ есть система, которую я называю «Стой и сражайся». Если игрок (или другой противник) близко привёл свою армию, сейчас нападёт, и у ИИ нет никаких шансов победить в войне со всеми собранными войсками, вместо бегства ИИ подыщет хорошую оборонительную позицию и будет ждать там вплоть до месяца, пока его не убьют. Таким образом вместо того, чтобы оттягивать неизбежное, но принимает последний бой в выгодной для себя местности. Игроку не придётся гоняться за его армиями по всему континенту, как это было в СК2, но происходит это будет только в очевидно выигранных игроком войнах.
Часто и сам игровой дизайн создавался с учётом ИИ, хотя бы в общих чертах. Мы уже рассказывали о механике крепостей, но вкратце: если вы зайдёте слишком далеко вглубь территорий врага, не осаждая крепости, ваши войска будут очень сильно страдать от истощения. Из-за этого ИИ практически никогда не будет заниматься подобным, так что если вы ещё не пересекли линию фронта, у вас будет время собрать войска и придумать план действий. Да и преследовать врага, отступающего вглубь своей территории, вы тоже вряд ли пожелаете. В совокупности это позволяет сосредоточиться на осадной войне, что отлично сочетается с игровой эпохой.
Это помогает достижению всех упомянутых мной целей: у ИИ остаётся меньше вариантов действий, так что мы можем сделать его умнее в выборе среди оставшихся. Игрок меньше негодует. И это подчёркивает исторические особенности того времени, попутно предотвращая глупые погони через полсвета.

Итак, насчёт военного ИИ поговорили, а что с остальным? Общий подход здесь остался схожим с СК2, хотя сделано всё с нуля. ИИ будет периодически проверять разные возможные действия, и совершит их, если в этом есть смысл. Элемент случайности на месте, и личность ИИ тоже влияет на набор действий, чтобы игра казалась живой, а не предсказуемой.
ИИ сильнее подвержен моддингу, чем в СК2, потому что система взаимодействий гораздо более открыта. Кое-что, конечно, всё ещё жёстко прописано в коде, но в целом свободы с изменением ИИ должно быть побольше, чем в СК2.
Повышенная свобода также значит, что нам будет проще балансировать ИИ, чем это было в СК2, потому что не придётся всё время привлекать к этому программистов. Это особенно пригодится, когда мы получим множество отзывов с выходом игры — такие архитектурные изменения позволят нам работать с ИИ быстрее, чем раньше.
Немалая часть того, что делают персонажи, обрабатывается при помощи событий, что ещё сильнее расширяет идеи СК2.

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

В общих чертах ИИ должен ощущаться похожим на СК2, но с большим упором на создание лучшего игрового опыта для игрока. После выхода игры нам будет проще улучшать ИИ, чем это было в СК2.

Обновление ПК

Забавно, что между началом написания этого дневника и отправкой его на публикацию я решил, что пора, наконец, обновить свой ПК. Я заменил старенький i7 4770K на модный современный Ryzen 9 3900X, и 16 GB памяти с частотой 2400 MHz на 32 GB с 3600 MHz.
Так что я перезаписал 1 минуту теста с полной многопоточностью, вот:

Видео загружается...

Как видите, игра работает так быстро, что я бы сказал, что играть в неё стало невозможно. За минуту прошло 1498 дней — на 56% больше, чем со старым процессором. ФПС тоже более стабилен, так что я очень доволен результатом.

Это всё, народ!
На следующей неделе мы ещё больше поговорим про моддинг.

Источник
ЕЩЁ ПО ТЕМЕ Crusader Kings 3 "Трейнер +19" [UPD: 07.03.2024] {MrAntiFun / WeMod} Crusader Kings 3 запускает масштабную инициативу, призванную помочь новым игрокам Crusader Kings 3 "Таблица для Cheat Engine" [1.12.4] {Recifense}
Комментарии: 0