#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Сегодня мы рассмотрим:

  • создание 3D-уровня с взаимодействующими объектами;
  • создание падающих блоков как многократно используемых объектов;
  • использование физического движка Godot.

Открываем наш проект с помощью кнопки Редактировать в менеджере проектов (показываю последний раз, в дальнейшем эту операцию опустим как повторяющуюся).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Мы видим нашу сцену на том месте, на котором мы остановились: добавлен корневой узел сцены Level1, добавлен узел камеры Camera3D.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Теперь мы добавим в нашу сцену пол (floor), по сути являющийся физическим объектом, с которым взаимодействуют все другие объекты. В панели Сцена выделяем корневой узел Level1 и нажимаем +. В поиск вводим StaticBody3D и добавляем выбранный узел. Static в данном случае означает, что данный физический объект не будет двигаться в нашей сцене, в отличие от анимированных объектов. Сразу переименуем новый узел и гордо назовём его Floor.

Жёлтый треугольник рядом с узлом Floor - это следующее предупреждение:

Ну, по факту так-то
Ну, по факту так-то

Значит, нужно добавить узлу StaticBody3D (наш Floor) форму (shape). Для этого выделим Floor и добавим уже дочерний к нему, а не к корневому узлу сцены, как раньше, узел MeshInstance3D.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Теперь, пока новый узел MeshInstance3D выделен, добавим ему некоторые свойства в Инспекторе: мы видим, что строка Mesh пуста, то есть у нашего узла нет никакой структуры (вершин, рёбер, полигонов).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Открываем выпадающий список в этой строчке и выбираем Создать BoxMesh.

Прогресс налицо
Прогресс налицо

Кроме изменений в Инспекторе, замечаем, что в рабочем пространстве у нас так же появился кубик.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Однако мы же хотели сделать пол, то есть наш кубик должен быть более вытянутым в длину и ширину, и более сжатым в высоту. Чтобы внести такие форменные изменения, в Инспекторе в строке Mesh кликаем на изображение нашего кубика, чтобы там же раскрыть его свойства.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Видим строку Size, и поскольку у нас X и Z - это ширина и длина объекта, а Y - его высота, сделаем наш кубик размерами 10х10х0.5.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Отлично, но помогло ли это нам избавиться от жёлтого треугольника рядом с узлом Floor в панели Сцена?

Nein!
Nein!

В описании проблемы указано, что нам нужно добавить дочерний узел CollisionShape3D, чтобы задать форму узлу StaticBody3D (наш Floor).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Мы не сделали этого раньше, потому что у нас не было меша для узла StaticBody3D, и узел CollisionShape3D в таком случае оставался бы без формы. А это же пол, мы же не хотим провалиться...

ПРЯМИКОМ В АД НАХ*Й!!!
ПРЯМИКОМ В АД НАХ*Й!!!

Исправляем. Выделяем наш Floor, и добавляем для него дочерний узел CollisionShape3D.

Опять треугольник -_-
Опять треугольник -_-

Кликаем на предупреждение, читаем, изучаем.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Как удачно, что мы буквально вот только создали объект формы MeshInstance3D. Для узла CollisionShape3D в Инспекторе есть специальная строка свойств - Shape.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Открываем выпадающий список и выбираем Создать BoxShape3D.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

И замечаем, что в рабочем пространстве у нас появился кубик, но странный.

Это наш CollisionShape3D
Это наш CollisionShape3D

Всё идёт к тому, что этому кубику нам нужно придать такие же размеры, как и узлу MeshInstance3D. Для этого в Инспекторе в строке Shape кликаем на выбранный нами ранее BoxShape, и в раскрытом окне свойств пишем для CollisionShape3D нужные значения (напомню, 10х10 и 0.5 в высоту).

Для придания узлу CollisionShape3D размеров можно также использовать эти красные точки на объекте в рабочем пространстве, растягивая нужные стороны нужным образом - но это получается не так точно
Для придания узлу CollisionShape3D размеров можно также использовать эти красные точки на объекте в рабочем пространстве, растягивая нужные стороны нужным образом - но это получается не так точно

Кажется, мы достигли успеха без предупреждений: теперь у узла StaticBody3D (наш Floor) есть физическая форма и форма, которая будет учитываться движком при обработке столкновений (речь об MeshInstance3D и CollisionShape3D соответственно, если вы не поняли).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Интересный момент: если в панели Сцена мы выделим узел Floor, который является корневым узлом для MeshInstance3D и CollisionShape3D, и будем с ним каким-либо образом взаимодействовать в рабочем пространстве (перемещать, вращать, изменять форму и т.д.), то изменяться будут и оба дочерних узла. Однако если работать только с одним дочерним узлом, то и изменяться будет только он. В целом, логично. Однако такое поведение может создать ситуацию, когда вроде бы единый объект Floor будет на самом деле "разбросан" по рабочему пространству из-за того, что мы, например, переместили CollisionShape3D, и теперь обработка столкновений происходит не на объекте, а где-то рядом.

Например, здесь CollisionShape3D поднят над мешем. Жесть
Например, здесь CollisionShape3D поднят над мешем. Жесть

Чтобы облегчить самим себе жизнь, сгруппируем все дочерние узлы нашего Floor-а. Для этого в панели Сцена выделим узел Floor, и в рабочем пространстве, в его верхней панели инструментов, нажмём на кнопку Сгруппировать выделенные узлы (Ctrl+G).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

После группировки дочерние узлы станут недоступны для выбора, и если мы в рабочем пространстве тыкнем на наш объект, то выберем сразу узел Floor.

А в панели Сцена после группировки возле корневого узла появится соответствующая иконка
А в панели Сцена после группировки возле корневого узла появится соответствующая иконка

Ну и кстати, продемонстрируем позитивные изменения в жизни узла Floor. Нажмём на кружок Z в правом верхнем углу рабочего пространства (там расположена специальная штука для ориентации в трёхмерном пространстве, будем называть её, например... гизмо, от слова gizmo), чтобы взглянуть на наш объект сбоку.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Очевидно, наш пол сейчас расположен выше нулевой отметки (оранжевая линия поперёк рабочего пространства, она же ось X). Берёмся за вертикальную зелёную стрелочку перемещения объекта по оси Y (то есть вертикальной оси) и перемещаем объект чуть ниже нулевой отметки.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Объект не рассыпался на составляющие, что не может не радовать.

Однако пора посмотреть на результат наших стараний со стороны: сохраняемся (Ctrl+S) и запускаем нашу сцену (F6).

Да, я тактично переместил камеру чуть назад, чтобы объять необъятное
Да, я тактично переместил камеру чуть назад, чтобы объять необъятное

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

Я хотел пошутить, а что-то уже не так смешно :(
Я хотел пошутить, а что-то уже не так смешно :(

Самое обидное, что всё серое только при запуске сцены, а в рабочем пространстве-то всё нормально. К слову, за то, чтобы в рабочем пространстве всё было красиво, отвечают эти две кнопки в панели инструментов.

Солнечный свет и окружение
Солнечный свет и окружение

Если мы их отключим, то...

Всё поломалось
Всё поломалось

Теперь в рабочем окружении мы видим всё таким, как оно есть. Очевидно, нам не хватает огонька в нашей работе. В панели Сцена выделяем наш самый родительский узел - Level1 - и добавляем ему дочерний узел DirectionalLight3D.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Посмотрим на наше солнышко в рабочем пространстве.

Да, это оно
Да, это оно

Приподнимем его по оси Y и немного повращаем.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

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

Отлично, сохраняем изменения и запускаем сцену.

Как тут и было
Как тут и было

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

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

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов
#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Дефолтные корневые узлы в панели Сцена нам не подходят, поскольку мы хотим создать не полноценную сцену, а один лишь объект. Поэтому нажимаем на + в панели Сцена и добавляем узел RigidBody3D, который может использоваться для физической симуляции (так у него в описании написано).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Дальше всё по накатанной: добавляем для корневого узла RigidBody3D дочерний MeshInstance3D и с помощью Инспектора задаём ему меш в виде куба (BoxMesh).

Да, тут я включил освещение и окружение - а то грустно всё это
Да, тут я включил освещение и окружение - а то грустно всё это

Следом добавляем её один дочерний узел CollisionShape3D и с помощью Инспектора задаём ему форму в виде куба (BoxShape3D).

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Поскольку мы не меняли стандартные размеры кубика при создании узла MeshInstance3D, то размеры кубиков обоих дочерних узлов совпали. Удобно!

Переименуем корневой узел RigidBody3D как Block и сохраним нашу дополнительную сцену.

Переименовали RigidBody3D мы, конечно, не просто так, а чтобы автоматом получить красивое название сохраняемого файла 
Переименовали RigidBody3D мы, конечно, не просто так, а чтобы автоматом получить красивое название сохраняемого файла 
Вот он, тута
Вот он, тута

Теперь осталось добавить Block на сцену Level1. Для этого в панели Сцена выделяем корневой узел Level1 и нажимаем на кнопку Инстанцировать дочернюю сцену (Ctrl+Shift+A), которая находится справа от привычной нам кнопки +.

Автор умеет в маркеры
Автор умеет в маркеры

В открывшемся окошке видим кнопку Нечёткий Поиск

Автор писал по теме курсовую
Автор писал по теме курсовую

...не обращаем на неё внимания и совершаем очевидный выбор.

Очевидный - это файл block.tscn
Очевидный - это файл block.tscn
Хоба!
Хоба!

Тут в обучающем видео нас, кстати, предупреждают от инстанцирования в качестве дочерней нашей текущей сцены (это если бы выбрали не block.tscn, а level_1.tscn) - ну, не очень-то и хотелось.

Обращаем внимание, что в рабочем пространстве выпал кубик.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

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

Красиво
Красиво

Кстати, вы заметили, что мы не группировали дочерние узлы, когда делали Block, а тем не менее в нашей текущей сцене он ведёт себя как единое целое? Магия, да и только.

Кстати (х2), вот эта иконка возле нашего Block позволяет, кликнув по ней, перейти на вкладку block, даже если мы её закроем. Удобно.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Кстати (х3), изменения во вкладке block, которые мы можем совершить над нашим Block, сразу же отобразятся во всех сценах, где мы этот Block используем. Крайне удобно.

Итак, запустим нашу сцену.

Бум

Выглядит неплохо, наш Block действительно падает. Однако кое-чего не хватает, и в данном случае не хватает теней. Добавим: выделим в панели Сцена узел DirectionalLight3D, в Инспекторе откроем свойство Shadow и включим эту опцию.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов
Другое дело!

Больше блоков богу блоков: выделяем в панели Сцена узел Block, изменяем его имя на Block1, кликаем на него правой кнопкой мыши и выбираем опцию Дублировать (Ctrl+D).

Вот так размножаются блоки
Вот так размножаются блоки

Да, всё верно, циферку 1 в имени Block мы поставили, чтобы движок при дублировании объекта автоматом поставил дубликату следующий номер.

Передвинем Block2 и немного покрутим.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов
Ну не прелесть ли?

Ещё, ещё! Зажимаем Shift, выделаем в панели Сцена сразу Block1 и Block2, дублируем, получаем ещё два блока.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

Перемещаем их, крутим-вертим.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов
Бесконечное веселье!

А сейчас финальный твист: переходим на вкладку block и делаем наш Block более Block-ным. По очереди меняем свойство Size у узла CollisionShape3D и у узла MeshInstance3D, делаем размер кубика по оси Y равным 0.5.

#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов
#2 Godot: 3D Platformer от BornCG. Объекты и физическое взаимодействие объектов

В рабочем пространстве вкладки block видны изменения.

Раньше это был кубик
Раньше это был кубик

Переходим на вкладку level_1, иии...

Ну кто бы мог подумать)
Ну кто бы мог подумать)

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

Подводя личные итоги - мой план работает (пока), обязательства перед самим собой и перед читателями (если таковые имеются) заставили меня сжать булки и дописать эту статью, которую я начал ещё в понедельник. Плюс, кажется, я так лучше запоминаю, что делаю.

Ждём продолжения.

Эт я в 8 часов утра, а ещё это Голден Бой
Эт я в 8 часов утра, а ещё это Голден Бой
4
2 комментария