Шаг за шагом: разработка 3D-игры в Godot 4.2 для начинающих

p0dbgfb70vpd63kwokvj4dpnoq0.png


И снова привет, Хабр! В прошлой статье я рассказал, как создавать 2D-игры на движке Godot. По вашим запросам — добавляем измерение и переходим в мир 3D. На этот раз мы погрузимся в трехмерные объекты и элементы анимирования. Подробности под катом!

Введение


Любая игра состоит из двух основных аспектов: дизайна и функциональной части. Создать дизайн для 3D-игр мне нравится больше, ведь он более «полноценный».

Поскольку я не дизайнером и не профессиональный разработчик, не буду с нуля создавать все объекты. Просто создам внешний мир, расставлю деревья, подготовлю окружение и саму поверхность. Для этого всего буду использовать готовый ассет. Но под конец статьи все же попробую самостоятельно создать 3D-объекты. Так что не переключайтесь.

qosm2wbok56o-xqniese_2auboo.png


Разработка дизайна


Если вы не читали первую часть и не знаете, как создать проект, — самое время сделать это, чтобы создать проект. Далее нужно указать корневой узел — 3D-сцену. По сути, это наш родительский класс, внутри которого будут все объекты будущей игры.

Создание мира


Создадим дочерний узел WorldEnvironment и перенесем в него объект World. По сути, это глобальное окружение, в котором мы можем указывать различные настройки отображения сцены. Например, какое освещение у нас будет на сцене.

uc7mtmzd8h00ljduhar7ocknfhw.png


Выбираем сам объект и в Инспекторе указываем, что создаем новое окружение и разрешаем его редактирование.

tg9isy7srzqak4eq31pjqi6bvte.png


Здесь заходим в background и видим, что в качестве фона установлен обычный цвет. Давайте это поменяем и укажем, что background будет неким материалом Sky — ProceduralSkyMaterial.

og8zygl7wn9t5wcczc1yu9iuivq.png


Дополнительно зайдем в town map и укажем, какой свет будет применяться к сцене. На данный момент указан Linear, его можно изменить, например, на Filmic.

_yjzsjsdsieceilkvpn2fdjqgzg.png


Кроме того, если хотите, можете увеличить яркость. Для этого просто увеличиваете Exposure. Я оставлю значение по умолчанию. При необходимости можете попробовать Auto Exposure.

w2ntdpqof-ygm7_rzllcohhytcy.png


Конечно, есть масса и других настроек. Например, мы можем изменить цвет окружения. Для этого переходим в ProceduralSkyMaterial / Sky и настраиваем отображение под свой проект. То же самое делаем с параметром Ground:

47aoxwvd7wq9zzedsi4y0_kf6w4.png


Следующим этапом попробуем добавить мир-ассет, установленный с сайта. Для заходим папку World, дальше — в source. Перетаскиваем объект в это пространство.

3fjwv3jqhnzixgnkv5f_ipuaogg.png


Расположим координаты мира по нулям, чтобы он находился в точке отсчета. Также скорректируем его размеры, чтобы все текстуры отображались корректно. Кроме того, поднимем его повыше, чтобы мир находился над условной сеткой. Должно получиться вот так:

9p-mgv7mg275sqsyuw3ea2qvv6o.png


Визуальное сопровождение


Следующим этапом добавим камеру. Нажимаем на родительский объект, кликаем на Добавить дочерний узел и выбираем обычную камеру.

4a7kgfme1vfuuvmexbx881gzmko.png


Добавим узел освещения, чтобы отображались тени и был свет.

dd9peiofsmytgbzslgxlmlkf8b0.png


Возможные ошибки переноса


Есть нюанс. Возможно, вы скачали другой ассет и самостоятельно попробовали его расположить на сцене. Но при этом он импортировался как «серый объект» без каких-либо цветов.

Это может быть связано с тем, что сам 3D-объект был некорректно экспортирован из первоначальной программы, в которой разрабатывался. Соответственно, в таком случае нужно всю папку с этим объектом забросить в Godot. Тогда, скорее всего, все текстуры загрузятся.

iqy23imorlhjii0cfnngvdmhiag.png


Остается сделать Ctrl + S — и готово.

Проектировка своих объектов


Теперь давайте попробуем создать свои собственные объекты внутри игрового движка. Для начала необходимо добавить новый дочерний узел — CSGCombiner.

tzw60kpqfoliwzfy5v9vixe4utw.png


Внутрь этого объекта мы можем поместить другие 3D-объекты. Все они идут с названием CSG, box, cylinder, mesh, polygon. Мы можем легко менять их размеры, например ширину или высоту, а также углы. Или вообще трансформировать в нечто абсолютно не похожее на первоначальную форму.

Простые объекты


Для начала добавим csgBox и посмотрим, как с ним можно взаимодействовать.

6jnx0paoiqr2nesgyxa0ktv8szm.png


Объект csgBox — это «нечто серое и пустое». Простая заготовка, на которую можно натянуть текстуру и добавить «твердотельность». Для этого выбираем сам объект, выбираем Material и нажимаем на <пусто> и указываем StandardlMaterial3D.

pk19_-9iwpxzgeltgbpiuf-hzkw.png


Следующее, что необходимо сделать, — выбрать этот материал. Переходим в Albedo. Здесь можем указать текстуру.

mqksdh6mvs5umhiii7lkhehdmjg.png


Мы можем настраивать визуальную часть текстуры объекта: изменять ее цвет, яркость и другие свойства. Таким образом, мы с вами создаем объект и можем легко изменять его характеристики. Но это не единственная особенность csgBox-объектов.

Усложненные объекты


Дополнительная особенность: мы объединять объекты и вырезать из них выделенные области. Давайте попробуем!

iu7okif4qetjft7x8cuhjkojcrc.png


Чтобы объединить объекты, достаточно оставить параметр в CSGShape3D, Operation — Union. А чтобы вырезать один объект из другого, Operation — Subtraction. Для создания объектов из нескольких, нужно создавать дочерние узлы от CSGCombiner. Выглядит это примерно так:

s38hm6rk8rz9ny9xn-yffkubxfk.png


Также для примера рассмотрим еще такой объект:

yjxd9r4k_cvhtu-fqdvjj_ntixe.png


Тут я использую узел CSGPolygon, он позволяет рассмотреть такую операцию как Mode — Spin, то есть мы задаем форму и прокручиваем по оси и получаем тело вращения. Также тут видно что мы можем менять цвет текстуры.

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

Поэтому мы давайте сделаем их твёрдыми объектами, к нашему счастью это делается максимально просто, мы выбираем CSGCombiner и здесь нам все что необходимо сделать так это установить галочку Use Collision

knh4pc77ld46jk7xvrn05fpd0ao.png


Создание каркаса


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

В WorldEnvironment добавляем новый дочерний узел StaticBody. По сути, это некий родительский элемент, внутри которого есть разные статичные объекты.

a0xo7pis62wo1gpcmebd7zmad9g.png


Добавим новый дочерний узел — CollisionShape и укажем CylinderShape. И все, что необходимо сделать, — это увеличить размеры самого объекта. Так нужно сделать для каждого предмета в сцене с которым вы будете взаимодействовать. Например, деревьями, колодцами и домами.

edknkmk5tnvtf9vfedfetmvlwxg.png


Создание основного игрока


Итак, мы можем приступить к разработке основного игрока. В качестве него можно использовать любой объект, например, скачанный с сайта SketchFab.

Я выбрал такую птичку, на которую можно в дальнейшем наложить свои анимации:

a_mio7wchpqqtnbmv5khdiyrbei.png


Далее разархивируйте папку с объектом и перетащите внутрь Godot. Лучше всего создать отдельную сцену с персонажем — так будет удобнее редактировать его.

Создаем узел CharacterBody3D, добавляем к нему персонажа и создаем узел CollisionShape, чтобы не было ошибок. Должно получиться вот так:

qwzfduncon-thdb27ivfjwuygzy.png


Теперь выбираем форму твердого объекта. Оптимальнее всего — CoupseShape, так как с ним проще работать

ehar3kgs9kdswgsbkucdknqfdwo.png


Скрипты


Прикрепляем скрипт к основному игроку и поэтому нажимаем на CharacterBody. Далее — на Новый скрипт.

buwrlbfsxabnnbawn5cqd6jdbjy.png


Начнем с обработки переменных, которая «вшита» в декоратор @export. Они контролируют скорость движения, прыжка, свободного падения и чувствительность мыши.

usw_o5hjy4gw3d8nb1jyjysewzy.png


Для обработки внутренних переменных использую:

nfuhdes6ujllaihf41box4pwj9a.png


movementInputVector используется для вектора движения персонажа по горизонтали (X и Z), а currentyYVelocity — для текущей вертикальной скорости (ось Y).

Мы добавили узел камеры. Чтобы он не был статичным и следовал за персонажем, нужно написать обработку движения мыши:

hg-z5rl_dhbgbklsx7gnbb7nadc.png


Функция _input обрабатывает события ввода. В данном случае, если событие — движение мыши (InputEventMouseMotion), персонаж поворачивается вокруг вертикальной оси (ось Y) на угол, пропорциональный движению мыши и чувствительности.

Обработка физики и движения выглядит так:

onbqq93insoeslo5h6hqkihbxae.png


Функция _physics_process вызывается каждый кадр и обрабатывает физику персонажа.

1. movementInputVector получает вектор движения из ввода пользователя (WASD или стрелки) и умножает его на скорость движения.

2. Если персонаж находится на земле (is_on_floor), вертикальная скорость (currentyYVelocity) сбрасывается в 0. Если пользователь нажимает кнопку прыжка (jump), вертикальная скорость устанавливается в значение jumpVelocity.

3. Если персонаж не на земле, к вертикальной скорости применяется гравитация, уменьшая ее на значение gravitySpeed. Но не более чем 2 000 единиц, что предотвращает бесконечное ускорение вниз.

4. Вычисляется итоговая скорость velocity, которая включает горизонтальное движение и вертикальную скорость. Горизонтальное движение преобразуется в соответствии с ориентацией персонажа (transform.basis).

5. move_and_slide автоматически обрабатывает столкновения объекта с другими объектами, которые имеют Collision.

Анимация персонажа


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

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

lghmiy6xc2dd4cvl8-i3dy0tyjo.png


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

lvgl5-wid0uvqghafmuf7q9uwdw.png


Теперь нам нужно добавить новый дочерний узел к персонажу — AnimationTree. С помощью него вы, по сути, определяете разные положения или анимации, которые есть у объекта. Далее в инспекторе выбираем тип анимации. Лично мне удобнее применить StateMachine, но вы можете использовать свой тип.

st2nm-go1z5ye5xresvys5llbwg.png


Справа мы можем перенести узел AnimationPlayer в параметр Anim Player, чтобы синхронизировать наши узлы анимаций. Внизу должно появиться пространство для создания блоков анимаций и настройки связности между ними.

gjp4xsmou3dkxviuhsmrlyn6gge.png


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

Используем соединитель узлов и проводим связи:

3uq0evvsctcsdq10obf2dhykx3i.png


Обычно при подключении двух блоков изображение начинает сходить с ума и работать некорректно. Дело в том, что наши задачи запускаются одновременно, но это просто исправить. Нажимаем на связь и в параметрах справа выбираем Advance–Condition. Прописываем условие — пусть это будет, например, ходьба.

echln4z3ueyhkxwh7m8v-rtrh6a.png


То же самое повторяем для другой связи, но в Condition указываем Idle. Если мы вернемся обратно в AnimationTree, то увидим, что в параметрах появились две новые функции, которые будем вызывать:

c7m-uqjoebyrjoycfa3dbxoldi8.png


Остался вопрос в том, как нам контролировать это через код. На самом деле, это действительно просто. Если мы перейдем к скрипту персонажа, мы можем настроить код для работы с переходом между состояниями:

yw2cfpbmraxfsq1_vqohn-mknq0.png


Тестирование


Нам остается лишь протестировать проект — нажимаем на иконку запуска. Если вы хотите экспортировать проект под запуск на определенной платформе, это можно сделать во вкладке проект–экспортировать.

hmgvecf--u4nxtx7d4soyehu1u4.png


Прежде чем мы выполним построение проекта под платформу, ее нужно будет скачать внутрь Godot.

jg_rwbblitsztnmbly6peea5xr4.gif


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

Что думаете насчет движка Godot вы? Поделитесь своим мнением в комментариях!

© Habrahabr.ru