Создание уровней в Godot: полное руководство

Создание уровней — ключевой аспект дизайна игр. Хорошо продуманные уровни задают структуру, предлагают вызовы и мотивируют игрока продвигаться дальше. Godot упрощает процесс: сцены, ноды и GDScript позволяют быстро собирать повторно используемые уровни и механики.
Определения (1–2 строки):
- Node2D — базовый узел для 2D-сцены, контейнер для графики и коллайдеров.
- CharacterBody2D — нод с удобствами для управления персонажем и обработки коллизий.
- StaticBody2D — статичный объект с коллайдером (платформы и препятствия).
Важно: примеры используют пиксельные координаты и стандартные переменные скорости из кода. При переносе в свой проект адаптируйте числовые значения под разрешение и масштаб вашей сцены.
Что вы получите после прочтения
- Как создать 2D-проект и добавить игрока.
- Рабочие скрипты для движения игрока и платформ.
- Менеджер уровней для переключения между сценами.
- Практические советы по дизайну, тестированию и локализации уровней.
Настройка проекта Godot для 2D
- Создайте новый проект в Godot и выберите 2D как профиль сцены.
- В корне сцены добавьте Node2D — он будет контейнером для всех объектов уровня.
- Создайте отдельную сцену для игрока:
- Новый Scene → CharacterBody2D (имя: Player).
- Внутри добавьте CollisionShape2D (прямоугольник) и Sprite для внешнего вида.
- Сохраните сцену игрока как Player.tscn и перетащите её в сцену уровня по необходимости.
Примечание: проект в примерах лицензирован MIT в исходном репозитории (см. ссылку в исходной статье). Следите за совместимостью версий Godot при переносе кода (различия между 3.x и 4.x могут влиять на API).
Создание двух уровней
Лучший способ организовать уровни в Godot — хранить каждый уровень как отдельную сцену (.tscn). Это упрощает повторное использование, правки и тестирование. В примере мы создаём две сцены: Level1.tscn и Level2.tscn с различными платформами и паттернами движения.
Скрипт игрока (Player)
Ниже — пример скрипта для CharacterBody2D. Он читает ввод, нормализует направление и применяет скорость.
extends CharacterBody2D
var speed = 300
func _physics_process(delta):
var input_dir = Vector2.ZERO
if Input.is_action_pressed("ui_left"):
input_dir.x -= 1
if Input.is_action_pressed("ui_right"):
input_dir.x += 1
if Input.is_action_pressed("ui_up"):
input_dir.y -= 1
if Input.is_action_pressed("ui_down"):
input_dir.y += 1
# Нормализуем направление, чтобы диагональное движение не был быстрее
velocity = input_dir.normalized() * speed
move_and_collide(velocity * delta)Пояснение: velocity хранит текущую скорость CharacterBody2D. move_and_collide автоматически обрабатывает столкновения с другими физическими телами.
Скрипт платформы (Platform)
Платформа в примере наследует StaticBody2D, но мы программно смещаем её через translate — это простой способ сделать движущуюся платформу без полноценной физики.
# Движение платформы
extends StaticBody2D
const move_speed = 100
var move_direction = Vector2(1, 0)
func _physics_process(delta):
var platform_movement = move_direction * move_speed * delta
translate(platform_movement)
# Меняем направление на краях пути (в примере 100..400)
if position.x > 400 or position.x < 100:
move_direction *= -1Советы: используйте Area2D для детекции игрока на платформе, если нужно переносить игрока вместе с поверхностью (проблема «скольжения» при перемещениях).
Менеджер уровней: плавное переключение между сценами
Менеджер уровней (Level Manager) отвечает за загрузку сцен-уровней, сохранение состояния и перенос игрока при смене уровня. В примере ниже при пересечении границ экрана вызывается switch_level(), который выгружает текущую сцену и подгружает следующую.
extends Node2D
var level_number = 1
var screen_size = Vector2()
var is_switching_level = false
func _ready():
screen_size = get_viewport_rect().size
load_level(level_number)
func load_level(level):
var level_path = "res://Level" + str(level) + ".tscn"
var level_scene = load(level_path)
var level_instance = level_scene.instantiate()
add_child(level_instance)
is_switching_level = false
func switch_level():
if is_switching_level:
return
is_switching_level = true
level_number += 1
if level_number > 2:
level_number = 1
# Предполагается, что нод игрока называется "Player"
var player = get_node("Node2D/Player")
if player:
var player_position = player.position
if player_position.x < 0:
player.position.x = screen_size.x
elif player_position.x > screen_size.x:
player.position.x = 0
elif player_position.y < 0:
player.position.y = screen_size.y
elif player_position.y > screen_size.y:
player.position.y = 0
# Удаляем старый уровень и загружаем новый
get_node("Node2D").queue_free()
load_level(level_number)
func _process(delta):
# Проверяем пересечение границ экрана
var player = get_node("Node2D/Player")
if player:
var player_position = player.position
var condition1 = player_position.x < 0
var condition2 = player_position.x > screen_size.x
var condition3 = player_position.y < 0
var condition4 = player_position.y > screen_size.y
if condition1 or condition2 or condition3 or condition4:
switch_level()Практическое замечание: вместо удаления всего Node2D можно выгружать только дочернюю сцену уровня, если есть общие GUI/менеджеры, которые должны оставаться.
Дополнительные фичи для уровней
Добавление механик делает уровни живыми. Ниже — расширенные рекомендации и примеры реализации.
Коллекционные предметы (Collectibles)
- Узлы: Area2D с CollisionShape2D и Sprite.
- Поведение: при входе игрока в область вызывается сигнал body_entered, предмет удаляется, увеличивается счётчик.
- Пример использования: монеты дают очки, ключи открывают двери.
Враги
- Различные типы ИИ: патруль, преследование, статичные ловушки.
- Архитектура: каждый враг как сцена с собственным скриптом; общая базовая сцена для поведения ускорит разработку.
- Баланс: вариативность поведения (замедление, ускорение, временное бессмертие у игрока).
Пауэр-апы
- Временные усиления: таймер запускается при подборе, по истечении сбрасывает эффект.
- Примеры: ускорение (умножитель скорости), неуязвимость, двойной прыжок.
Головоломки
- Условия прогресса: переключатели, блоки, которые нужно переместить, комбинации для открытия дверей.
- Подсказки: визуальные маркеры и звук, если игрок застрял.
Лучшие практики дизайна уровней
Баланс сложности
- Кривая сложности: ввод новых механик в безопасной зоне, постепенное усложнение.
- Тестирование: A/B тесты с разными настройками и сбор фидбека.
Поощрение исследования
- Скрытые зоны и пасхалки увеличивают вовлечённость и время в игре.
- Вознаграждения должны быть соразмерны усилиям.
Тестирование и итерация
- Регулярно проводите playtest с разными типами игроков.
- Наблюдайте: где игроки застревают, где делают ошибки.
Визуал и звук
- Контраст между интерактивными объектами и фоном.
- Лицензии: используйте аудио без нарушения прав.
Поток уровня
- Ведите игрока визуально: свет, цвет, линии платформ.
- Избегайте тупиков и непреднамеренных ловушек.
Шаблон: пошаговый план создания уровня (Playbook)
- Идея и цель уровня: что игрок должен сделать?
- Блокировка основных областей на бумаге/whiteboard.
- Быстрая сборка прототипа: простые платформы, игрок, одна механика.
- Playtest 1: наблюдение, правки.
- Добавление вторичных механик: враги, предметы.
- Полировка: музыка, эффекты, оптимизация.
- Итоговое тестирование и критерии приёмки.
Чек-листы по ролям
Дизайнер уровней:
- Определена цель и тема уровня
- Есть вводные зоны и зона обучения механике
- Проверены альтернативные маршруты
Программист:
- Скрипты персонажа и платформ корректно работают
- Менеджер уровней переключает сцены без ошибок
- Сохранение/загрузка состояния (если нужно) протестировано
Тестировщик:
- Нет мест, где игрок застревает навсегда
- Все интерактивные объекты имеют обратную связь
- Проверена локализация текстов
Критерии приёмки
- Уровень загружается и выгружается без падений приложения.
- Игрок может пройти от старта до финиша без багов, блокирующих прогресс.
- Счётчики и предметы корректно обновляют состояние.
- Производительность не падает на целевых платформах (память и FPS в пределах ожидаемого).
Тестовые случаи (пример)
- Движение игрока по горизонтали и вертикали — ожидаемая скорость и коллизии.
- Пересечение границ экрана — переключение на следующий уровень и корректное позиционирование игрока.
- Подбор коллекционных предметов — увеличение счёта и удаление предмета.
- Взаимодействие с движущейся платформой — игрок не проваливается через платформу.
- Загрузка/выгрузка уровня — отсутствие утечек памяти при многократном переключении.
Ментальные модели и эвристики
- «Учить через игру»: вводите одну новую механику на каждые 1–2 уровня.
- «Закон обратной связи»: каждое действие игрока должно давать визуальную или звуковую реакцию.
- «Минимальная безотказность»: если игрок теряет прогресс, должен быть честный способ его восстановить.
Сравнение подходов к созданию уровней
- Сцена на уровень (.tscn): простота, быстрое редактирование, удобная загрузка/выгрузка.
- TileMap + чанки: экономно для больших миров, сложнее динамически изменять.
- Stream (потоковая подгрузка): подходит для огромных карт и экономии памяти.
Выбор зависит от размера игры: небольшие аркады — отдельные сцены; большие платформеры — TileMap/stream.
Совместимость и локализация для России
- Единицы измерения: чаще используют пиксели/пиксельные размеры, часы/минуты для таймеров — оставляйте стандартными.
- Тексты интерфейса: переводите строки UI, и учитывайте увеличение длины текста при русском переводе (могут «вылезать» кнопки).
- Аудио: убедитесь в лицензировании музыки для РФ/ЕС/США (если используете платные треки).
Факт-бокс: ключевые параметры из примеров
- Скорость игрока: speed = 300 (единицы: пиксели/сек).
- Скорость платформы: move_speed = 100 (пиксели/сек).
- Диапазон движения платформы в примере: x в пределах 100..400.
- Поддерживаемое переключение уровней: пример использует 2 уровня, но менеджер масштабируемый.
Диаграмма: схема переключения уровня (Mermaid)
flowchart TD
A[Игрок движется] --> B{Пересечена граница экрана?}
B -- Нет --> A
B -- Да --> C[Вызвать switch_level'']
C --> D[Сохранить позицию игрока]
D --> E[Удалить старую сцену]
E --> F[Загрузить новую сцену]
F --> G[Восстановить позицию игрока]
G --> AКогда описанный подход не сработает (контрпримеры)
- Огромные уровни с множеством тайлов и объектов: сцена-на-уровень приведёт к проблемам с памятью; лучше использовать TileMap и потоковую подгрузку.
- Сеть/мультиплеер: синхронизацию состояния уровней придётся строить отдельно (серверная логика), простая локальная смена сцен не обеспечит консистентность.
Откат и инцидентный план
Если при загрузке уровня происходит ошибка:
- Логируйте причину: путь сцены, исключение.
- Откат к предыдущему корректному состоянию (загрузить резервную сцену или меню).
- Отправить диагностическую заметку: игровой стейт, версия движка, стектрейс.
Краткое резюме
- Разделяйте уровни на отдельные сцены для простоты разработки.
- Используйте менеджер уровней для унифицированной логики загрузки и сохранения состояния.
- Тестируйте и итерируйте: баланс, визуальные подсказки и звук критичны для качества уровня.
Важное: начните с простого прототипа и расширяйте механику по мере получения фидбека от игроков.
Краткое резюме в одной строке: уровни в Godot создают структуру игрового опыта — проектируйте их как отдельные сцены, тестируйте и добавляйте фичи постепенно.
Похожие материалы
Создать визитку в Canva: пошагово и профессионально
NPER в Excel — число периодов выплат
Конвертация WebP из DALL·E 3 в PNG или JPEG
Как правильно чистить настольный ПК
Chrome сохраняет WebP: как скачать в JPG/PNG