Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Поява монстрів
У цій частині ми збираємося випадковим чином створювати монстрів уздовж шляху. Зрештою, у вас будуть монстри, що бродять по ігровій дошці.

Двічі клацніть main.tscn у доку FileSystem, щоб відкрити сцену Main.
Перш ніж малювати шлях, ми збираємося змінити роздільну здатність гри. Наша гра має стандартний розмір вікна 1152x648. Ми встановимо для нього 720x540, гарне маленьке поле.
Перейдіть до Проект -> Параметри проекту.

Якщо у вас Input Map все ще відкрита, переключіть вкладку на General.
У лівому меню перейдіть до пункту Дисплей -> Вікно. Праворуч встановіть для параметра Ширина області перегляду значення 720, а для параметра Висота області перегляду значення 540.

Створення шляху на якому з'являтимуться монстри
Як і в підручнику з двовимірної гри, ви збираєтеся спроектувати шлях і використовувати вузол PathFollow3D для вибірки випадкових місць на ньому.
У 3D, однак, це трохи складніше. Ми хочемо, щоб він був навколо виду гри, щоб монстри з'являлися прямо за екраном. Але якщо ми намалюємо шлях, ми не побачимо його з попереднього перегляду камери.
Щоб знайти межі перегляду, ми можемо використовувати деякі сітки-заповнювачі. Ваше вікно перегляду все одно має бути розділене на дві частини, з попереднім переглядом камери внизу. Якщо це не так, натисніть Ctrl + 2 (Cmd + 2 на macOS), щоб розділити перегляд на два. Виберіть вузол Camera3D і натисніть прапорець Попередній перегляд у нижньому вікні перегляду.

Додавання циліндрів-орієнтирів
Додамо сіті-заповнювачі. Додайте новий Node3D як дочірню вершину Main і назвіть її Cylinders. Ми будемо використовувати його для групування циліндрів. Виділіть Cylinders і додайте дочірній вузол MeshInstance3D

В Інспекторі властивості Mesh призначте CylinderMesh.

Оберіть вигляд згори верхній ортогональний використовуючи меню вікна перегляду в лівому верхньому кутку, або скориставшись клавішею 7 цифрової клавіатури.

Сітка може відволікати. Ви можете перемкнути його, перейшовши до меню Перегляд на панелі інструментів і натиснувши Перегляд сітки.

Тепер вам треба перемістити циліндр вздовж наземної площини, дивлячись на попередній перегляд камери в нижньому вікні перегляду. Я рекомендую робити це використовуючи прив'язку до ґратки. Ви можете перемикати прив'язку, клацаючи значок магніту на панелі інструментів, або натискаючи Y.

Перемістіть циліндр так, щоб він опинився поза полем зору камери у верхньому лівому куті.

Ми збираємося створити копії меша і розмістити їх навколо ігрової зони. Натисніть Ctrl + D (Cmd + D на macOS), щоб дублювати вузол. Також можна клацнути правою кнопкою миші вузол на панелі Сцена та вибрати пункт Дублювати. Переміщуйте копію вниз по синій осі Z, доки вона не вийде за межі попереднього перегляду камери.
Виберіть обидва циліндри, натиснувши клавішу Shift і клацнувши по невибраному, і дублюйте їх.

Перемістіть їх праворуч по червоній осі X.

Білі циліндри трохи важко розгледіти, чи не так? Давайте виділимо їх, надавши їм новий матеріал.
У 3D матеріали визначають візуальні властивості поверхні, такі як її колір, те, як вона відбиває світло, тощо. Ми можемо використовувати їх для зміни кольору меша.
Ми можемо оновити всі чотири циліндри одночасно. Виберіть усі екземпляри сітки в доці Scene. Щоб зробити це, ви можете клацнути на першому та клацнути Shift на останньому.

У Inspector розгорніть розділ Material і призначте StandardMaterial3D для слота 0.

Клацніть піктограму сфери, щоб відкрити ресурс матеріалу. Ви отримуєте попередній перегляд матеріалу та довгий список розділів, заповнених властивостями. Ви можете використовувати їх для створення всіляких поверхонь, від металу до каміння, чи води.
Розширте секцію Albedo.
Виберіть колір, який контрастує з фоном, наприклад, яскраво-помаранчевий.

Тепер ми можемо використовувати циліндри в якості орієнтирів. Згорніть їх на панелі Сцена натиснувши сіру стрілку поруч з ними. Надалі, ви також можете перемикати їх видимість, клацнувши значок ока поруч із Cylinders.

Додайте дочірній вузол Path3D до Main вузла. На панелі інструментів з'являються чотири значки. Натисніть інструмент Додати точку, значок із зеленим знаком «+».

Примітка
Ви можете навести курсор на будь-яку піктограму, щоб побачити підказку з описом інструмента.
Клацніть по центру кожного циліндра, щоб створити точку. Потім клацніть піктограму Закрити криву на панелі інструментів, щоб закрити контур. Якщо якась точка трохи за межами, можете натиснути на неї і перетягнути, щоб змінити розташування.

Ваш шлях повинен виглядати так.

Для вибірки випадкових позицій на ньому нам потрібен вузол PathFollow3D. Додайте PathFollow3D як дочірній елемент Path3D. Перейменуйте два вузли на SpawnLocation і SpawnPath відповідно. Це більш опис того, для чого ми їх використовуватимемо.

З усім цим ми готові кодувати механізм появи монстрів.
Поява монстрів
Клацніть правою кнопкою миші вузол Main і приєднайте до нього новий скрипт.
Спочатку ми експортуємо змінну в Inspector, щоб ми могли призначити їй mob.tscn або будь-якого іншого монстра.
extends Node
@export var mob_scene: PackedScene
using Godot;
public partial class Main : Node
{
// Don't forget to rebuild the project so the editor knows about the new export variable.
[Export]
public PackedScene MobScene { get; set; }
}
Ми хочемо, щоб моби народжувалися через певні проміжки часу. Для цього нам потрібно повернутися на сцену і додати таймер. Але перед цим нам потрібно присвоїти файл mob.tscn властивості mob_scene вище (інакше вона буде нульовою!)
Поверніться до 3D-екрана та виберіть вузол Main. Перетягніть mob.tscn із дока FileSystem до слота Mob Scene в Inspector.

Додайте новий вузол Timer як дочірній вузол Main. Назвіть його MobTimer.

У Інспекторі встановіть час очікування Wait Time на 0.5 секунди та увімкніть автозапуск Autostart, щоб таймер автоматично запускався разом із грою.

Таймери випромінюють сигнал timeout кожного разу, коли вони досягають кінця свого часу очікування Wait Time. За замовчуванням вони перезавантажуються автоматично, випромінюючи сигнал в циклі. Ми можемо підключатися до цього сигналу від головного вузла Main, щоб налаштувати появу монстрів кожні 0.5 секунди.
З вибраним MobTimer перейдіть до панелі Signals праворуч і двічі клацніть сигнал timeout.

Підключіть його до головного вузла Main.

Це поверне вас до сценарію з новою порожньою функцією _on_mob_timer_timeout().
Давайте кодувати логіку появи монстрів. Ми збираємося:
Вставити екземпляр (інстансувати) сцени монстра.
Отримати випадкове положення на шляху появи.
Отримати позицію гравця.
Викликати метод монстра
initialize(), передаючи йому випадкову позицію і позицію гравця.Додати монстра в якості нащадка головного вузла Main.
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on the SpawnPath.
# We store the reference to the SpawnLocation node.
var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
# And give it a random offset.
mob_spawn_location.progress_ratio = randf()
var player_position = $Player.position
mob.initialize(mob_spawn_location.position, player_position)
# Spawn the mob by adding it to the Main scene.
add_child(mob)
// We also specified this function name in PascalCase in the editor's connection window.
private void OnMobTimerTimeout()
{
// Create a new instance of the Mob scene.
Mob mob = MobScene.Instantiate<Mob>();
// Choose a random location on the SpawnPath.
// We store the reference to the SpawnLocation node.
var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
// And give it a random offset.
mobSpawnLocation.ProgressRatio = GD.Randf();
Vector3 playerPosition = GetNode<Player>("Player").Position;
mob.Initialize(mobSpawnLocation.Position, playerPosition);
// Spawn the mob by adding it to the Main scene.
AddChild(mob);
}
Вище randf() створює випадкове значення між 0 і 1, що є тим, що очікує progress_ratio вузла PathFollow: 0 – початок шляху, 1 це кінець шляху. Шлях, який ми встановили, пролягає навколо вікна перегляду камери, тому будь-яке випадкове значення між 0 і 1 є випадковою позицією вздовж країв вікна перегляду!
Зазначте, що якщо ви вилучаєте Player з головної сцени, наступний рядок
var player_position = $Player.position
Vector3 playerPosition = GetNode<Player>("Player").Position;
дасть помилку, тому що тут нема $Player!
Ось повний скрипт main.gd для довідки.
extends Node
@export var mob_scene: PackedScene
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on the SpawnPath.
# We store the reference to the SpawnLocation node.
var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
# And give it a random offset.
mob_spawn_location.progress_ratio = randf()
var player_position = $Player.position
mob.initialize(mob_spawn_location.position, player_position)
# Spawn the mob by adding it to the Main scene.
add_child(mob)
using Godot;
public partial class Main : Node
{
[Export]
public PackedScene MobScene { get; set; }
private void OnMobTimerTimeout()
{
// Create a new instance of the Mob scene.
Mob mob = MobScene.Instantiate<Mob>();
// Choose a random location on the SpawnPath.
// We store the reference to the SpawnLocation node.
var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
// And give it a random offset.
mobSpawnLocation.ProgressRatio = GD.Randf();
Vector3 playerPosition = GetNode<Player>("Player").Position;
mob.Initialize(mobSpawnLocation.Position, playerPosition);
// Spawn the mob by adding it to the Main scene.
AddChild(mob);
}
}
Ви можете протестувати сцену, натиснувши F6 (Cmd + R на macOS). Ви повинні побачити, як монстри з'являються та рухаються по прямій лінії.

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