Я хочу рассказать сообществу об эксперименте, который я провел.
Мне всегда нравились игры с физикой.
То есть некоторые процессы не управляются скриптами, а развиваются со временем, подчиняясь физическим законам.
Это приводит к сложности и непредсказуемости игрового процесса.
Есть много примеров; физические элементы тонко пронизывают разнообразие компьютерных игр.
Возьмите любой платформер: совершенно другие ощущения от игры, когда есть инерция персонажа, скольжение, гравитация, урон от падения с большой высоты и отдача от оружия.
Или те же гонки: насколько приятнее на полной скорости сбивать людей, рекламные щиты и кучи мусора, чтобы они разлетались во все стороны, вместо того, чтобы моментально остановиться, врезавшись в намертво вросший в землю столб.
Или еще один замечательный пример — космическая программа Кербала.
Там физика уже является прямым источником геймплея.
Или, например, жанр 2D-артиллерии.
Частично его очарование основано на разрушаемой, динамичной земле.
Но насколько было бы лучше, если бы земля не просто рассыпалась линейно, а вела себя реалистично, разлетаясь на куски от взрывов.
Я давно мечтал сделать именно такой физически реалистичный ремейк Scorched Earth. Но все мои эксперименты с моделированием физических систем упирались в неумолимо медленные процессоры.
Тысяча или две частицы были пределом для моделирования в реальном времени.
Но мое недавнее «открытие» изменило ситуацию.
Мы живем во время бурного развития игрового оборудования.
Развивались в основном видеокарты, ведь производители игр с наибольшим энтузиазмом относились к увеличению графической составляющей игр, а производители железа поддерживали высокий fps. И неудивительно, что Nvidia решила добавить разработчикам возможность писать код для графической системы, то есть проводить вычисления в графическом ядре.
На мой взгляд, это решение было тихой революцией.
Я, конечно, знал, что видеокарта мощнее процессора, но не знал, насколько.
На среднестатистическом игровом компьютере производительность видеокарты в 50-100 раз превышает производительность центрального процессора.
Конечно, задача должна хорошо распараллеливаться; этот бонус не актуален ни для одного алгоритма.
Но моделирование тысяч частиц прекрасно распараллеливается.
Осознав это, я понял, что могу наконец создать полностью физическую игру, в которой не будет заскриптовано ничего, кроме физики.
Игра станет эквивалентом физической симуляции.
Я давно делаю игры на Unity, и был рад узнать, что в этом движке реализован класс ComputeShader, который позволяет использовать в вашем проекте шейдеры на языке HLSL. Мы просто пишем шейдер, связываем его с экземпляром ComputeShader и отправляем в Update. Приступить к параллельным вычислениям на графических процессорах было непросто.
Учебников недостаточно, а те, что существуют, весьма ограничены в объеме излагаемых тонкостей.
Но ключевых сложностей было не так уж и много, справочной информации по HLSL на msdn было довольно много, так что каким-то образом методом проб и ошибок я освоил специфику и начал делать игру.
Задача была проста: нужно в реальном времени смоделировать несколько десятков тысяч взаимодействующих частиц и построить из них мир, который будет жить по своим законам.
Параллельные вычисления — сложная штука.
Необходимо было свести все расчеты к простым блокам одинакового размера, чтобы для каждой частицы был один поток.
Я решил максимально упростить математику взаимодействия частиц.
Например, можно обойтись без интегратора, просто измерить величину поля (описывающего взаимодействие частиц) в текущей точке и на основании этого изменить скорость частицы.
Простота гарантировала, что все потоки будут выполняться одинаково быстро и не будет тяжелых потоков, которые другим пришлось бы ждать.
Кроме того, при взаимодействии с частицами нужно было работать с данными в защищенном режиме, чтобы параллельные потоки знали об одновременной записи и чтении и не путались.
Ведь если частица может одновременно взаимодействовать с десятком других частиц, все они одновременно могут менять свою скорость, а значит, делать это необходимо в защищенном режиме.
HLSL нашел для этого средства.
Правда, операторы типа InterlockedAdd() работают только с целыми значениями, поэтому нам пришлось пожертвовать точностью и хранить скорость в видеопамяти как целые значения.
Огромные массивы взаимодействующих частиц – тоже коварная штука.
Необходимо было упростить сложность расчетов с
к чему-то вроде
Я добился этого, создав двумерную сетку 256x256, и в каждом ее элементе на каждом шаге сохранял ссылки на все близлежащие частицы, чтобы при расчете взаимодействия частиц каждая частица взаимодействовала только с теми частицами, которые находятся в пределах нескольких Элементы сетки 3х3.
Кстати, почему я создал свой собственный вместо уже реализованного в Unity физического движка? Потому что универсальный физический движок, подходящий для широкого круга задач, связанных с моделированием системы твердых тел, плохо подходит для моделирования системы взаимодействующих материальных точек.
Я предпочел оригинальный двигатель, оптимизированный под специфику.
Если вы создадите в Unity тысячу объектов с твердым телом, то увидите, что fps падает весьма существенно.
В моем случае мне нужны десятки тысяч частиц, и движок, написанный с нуля, позволяет мне рассчитывать их с хорошим fps. Дискретное моделирование физического взаимодействия – опять-таки непростая задача.
Чем больше шаг, тем больше ошибка.
Взаимодействие между частицами осуществляется через силу Леннарда-Джонса, то есть при сближении частиц сила отталкивания возрастает до двенадцатой степени.
Это значительно увеличивает ошибку, связанную с большим шагом.
Проще говоря, материя взрывается, нарушая закон сохранения энергии.
Возникает противоречие: нам нужно быстрое моделирование в реальном времени.
Но шаг должен быть очень маленьким.
Я разрешил это противоречие, уменьшив шаг в десять раз по сравнению с первыми экспериментами и выполнив десять циклов моделирования в каждом Update().
Цена этого решения — производительность.
Поэтому нам пришлось значительно сократить количество частиц.
Но их еще достаточно для сложного поведения всей системы.
Что ж, я реализовал еще пару десятков трюков, чтобы добиться удовлетворительного поведения материи.
Например, я ввел аналог валентных связей между частицами, которые распределяют импульс и скорость частицы между ее соседями.
Или, например, гравитация действует не во всем объеме Земли, а воздействует только на верхний слой частиц.
Но если в воздух взлетят крупные куски материи, гравитация окажет на них полное влияние.
Это реализуется путем построения гравитационной маски на каждом шаге и ее учета в расчетах.
И таких тонкостей еще много; Я не хочу слишком углубляться в эти подробности.
На решение всех проблем с параллельными вычислениями и физикой ушло около четырех месяцев в режиме хобби, и в какой-то момент удалось перейти на геймплейный уровень.
Что произошло в конце? В результате получилась игра в жанре «2D-артиллерия», вроде Pocket Tanks, Scorched Earth или Worms. Вот длинное десятиминутное видео, в котором также показан геймплей, но более подробно: Вы можете заметить, что земля и здания выглядят как желе.
Это исправлено за счет производительности.
Можно уменьшить шаг и увеличить коэффициент влияния полей на скорость частицы.
Но сейчас я стараюсь поддерживать игру на уровне, не слишком обременительном для большинства не слишком старых видеокарт. Допустим, на моей карте GTX 750m, имеющей 384 ядра, игра с 20 тысячами частиц работает со скоростью 25 кадров в секунду, что делает ее вполне играбельной.
Здесь есть два вывода, объективный и субъективный: 1. Видеокарта обладает огромной мощностью, и теперь непреодолимых технических барьеров, мешающих разработчикам использовать ее для вычислений, больше нет. Это может открыть для практического использования ранее недоступные (из-за вычислительной сложности) подходы к игровому процессу.
2. Очень необычные ощущения возникают от игры в физически реалистичной песочнице.
И на мой взгляд здесь зарыто немало неожиданных идей в области геймплейного дизайна.
И хотелось бы, чтобы разработчики больше экспериментировали с внедрением физики в геймплей, ведь свет не сходился клином на графике.
Теги: #физика #симуляция #артиллерия #эксперимент #gpu #компьютерные шейдеры #песочница #gamedev #разработка игр #Параллельное программирование #unity
-
Ruby On Rails Шаг За Шагом. №1 Теория
19 Oct, 24 -
Форекс 3.0.10
19 Oct, 24 -
Текст В Строку Или Как Победить Дизайнера
19 Oct, 24