Логотип проекта The Great Tribes

Дневник разработки №33

Дневник разработки №33

Всем привет! И с прошедшими новогодними праздниками!

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

Согласно плану разработки был реализован первый контакт с ИИ:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Внизу скриншота видны сообщения о пересечении зон контроля армии с другой армией и городом. Теперь предстояло разработать некий элемент интерфейса который бы отображал данные события:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)
Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Далее были реализованы первые маневры ИИ. ИИ ходит по карте и пытается определить границы своего материка. В видео у Дуката https://youtu.be/69G51u_Mq3g?t=693 ,есть момент где он бегает за армией противника, который не обращает на него внимания, так как занят исследованием карты :)

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

На средней карте при максимальном отдалении и большом скоплении пальм - это просто жуть! 15 824 756 треугольников! Почти 16 миллионов!!!

Немного погенерировав карты я нашел место с 16,75 миллионами :)

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Хотя вот подобное место с елками давало всего 8,5 миллионов треугольников:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

А в среднем сцена состояло из примерно 4 миллионов:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

На 40% снизился полигонаж елок! Отличий практически не видно.

Следом мы переделали и пальмы - полигонаж на пальмах был снижен в 10 раз. 600 - 700 против шести тысяч полигонов в одном паке.

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Параллельно пока шла работа над моделями я занялся вопросом упрощения геометрии террайна. Вот как он выглядел до оптимизации:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

И после первых шагов:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)
Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)
Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Но это было все сделано простым методом — все ровные тайлы были заменены двумя треугольниками вместо 882.

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Строить по ним выпукло-вогнутый контур (Concave Hull). С Convex Hull`ом проблем не было, я уже использовал алгоритм Грэхема (Graham scan). А вот построением Concave Hull появилась проблема... Информации на эту тему тему в интернете найти оказалось достаточно сложно. Пришлось писать реализацию алгоритмов с нуля. Не совру, если я скажу что прочитал с десяток разных диссертаций на эту тему. Но все предложенные алгоритмы давали приближенный результат с некоторой погрешностью. После недели мучений и боли мне пришла идея своего алгоритма, возможно я его когда-нибудь опишу :)
В результате уже двух недельного мучения я получил искомый результат и смог строить Concave Hull практически любой сложности, обходя стороной множества с дырками, просто разделяя их на 2 половины по дырке. Получал контур и триангулировал его:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)
Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

[/spoiler]
Получая на выходе такой результат:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Также подвергся упрощению туман войны:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

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

3 дня я проиграл в ATOM RPG снимая стресс :) Даже на работу не ходил. Слава богу у нас в это время термометр зашкаливал на границе -44 - -46 градусов по Цельсию. И свою хандру я выдал за отмазку о не заводившейся машине.

И вот перед новогодними праздниками, вдоволь наигравшись, но правда не пройдя игру, я выдал новую облегченную версию алгоритма, который подходил только под мои условия тайлов. Вычисления данных для оптимизации были не заметны на фоне генерации карты и количество полигонов снижалось в среднем на 40-50%.
Но появились артефакты при отрисовке воды, пришлось переписать все алгоритмы связанные с водой.
Вот результат:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Анатолий тем временем сделал юнит кочевья:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Пока он лежит отдыхает :)

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

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Горы стали более рельефными, это заметно без текстуры, так как текстура теперь к ним не подходит:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

По сетке так вообще отличия очевидны:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Осталось дело за малым — нужна новая текстура гор.

Следующим этапом пришлось переписать загрузчик ресурсов и генератор карты. Попутно переделав стартовое меню под эти все дела:

Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)
Дневник разработки №33 — The Great Tribes — DevTribe: Разработка игр (Java, open gl)

Теперь загрузка ресурсов идет параллельно и после чего начинается генерация карты.

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

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

Подведем итоги проделанной работы:

  • Оптимизация графики с программной стороны.
  • Оптимизация графики — модели.
  • Серверная часть.
  • Разбитие рендера на 3 потока.
  • Предзагрузка ресурсов (текстур и моделей).
  • Переписал шейдеры тумана войны, воды и террайна.
  • Сократил потребление оперативной памяти на 20-30%
  • Реализован ряд элементов UI
  • Переделано стартовое окно с новым UI.
  • Устранил ошибки в расчетах нормалей.
  • Подправил холмы.
  • Новые горы.
  • Ввели нормалмапу для террайна.
  • Новое выделение юнитов.
  • Новая анимация юнитов.
  • Окно дипламатии.
  • Действия ИИ. Исследование карты.
  • Действия ИИ. Дипломатический контакт.
  • Действия ИИ. Заключение мира, дружбы или объявление войны.
  • Действия ИИ. Действие юнитов при столкновении.

В общем была проделана огромная работа по оптимизации и не много по игровым механикам. Надеюсь в этом месяце в се пойдет по плану и я наконец-то допишу города :)

Спасибо за внимание!
Вступайте в нашу группу в ВК: https://vk.com/thegreattribes



Хороший отчет, 16 милионов полгинов на один экрна это конечно мощно :D
У меня сейчас в игре кст тоже есть проблема с производительности на одном ядре, но там проблема не в графике, а в алгоритмах ИИ юнитов и прочих штуках

alexprey, Я сразу закладывал потенциал на то что ИИ будут в отдельных потоках. Сейчас у меня получается не более 4 миллионов полигонов с новыми пальмами.

Zemlaynin, а у тебя невидимые области не рендерятся? Ну в пошаговых с ии попроще чем в реал тайме)

Конечно не рендерятся. Ну я бы не сказал что прям вот так проще :)

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

alexprey, Ня я бы не считал каждый кадр, а некий тик

Вышла статья на Хабре https://habr.com/post/436040/