Гид по технологиям

Цикл «день‑ночь» в Godot 4: практическое руководство

6 min read Game Dev Обновлено 30 Dec 2025
Цикл день‑ночь в Godot 4
Цикл день‑ночь в Godot 4

человек играет в шутер с контроллером

Цикл день‑ночь добавляет в игру атмосферу, разнообразие визуальных состояний и открывает новые механики (например, враги активны только ночью). В Godot 4 это можно реализовать компактно и гибко — ниже вы найдёте проверенные подходы и шаблоны кода для 2D‑проекта.

Что вы получите из статьи

  • Готовый шаблон DayNightManager с плавными переходами и звуками.
  • Примеры кода GDScript для Godot 4 с объяснениями.
  • Варианты визуализации (ColorRect, Light2D, шейдеры) и когда что выбрать.
  • Чек‑листы для программиста, художника и дизайнера.
  • Критерии приёмки и тесты для фазы QA.

Одно предложение о терминах

DayNightManager — узел, управляющий временем суток и триггерящий визуальные/аудиоэффекты; Transition — плавный переход между состояниями.

Подготовка проекта и базовая сцена

  1. Создайте новый 2D‑проект в Godot 4.
  2. В сцену добавьте корневой узел (Node2D) — он будет хранить логику дня/ночи.
  3. Создайте игрока как CharacterBody2D с CollisionShape2D и Sprite2D.
  4. Добавьте Timer (переименуйте в DayNightTimer) и ColorRect (переименуйте в BackgroundRect) и два AudioStreamPlayer2D для звуков дня и ночи.

Пример простой логики движения игрока (прикрепите к CharacterBody2D):

extends CharacterBody2D

@export var speed: float = 300.0

func _physics_process(delta: float) -> void:
    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)

Этот скрипт даёт базовое перемещение игрока четырьмя направлениями (стрелки или назначенные действия).

игра godot с квадратным узлом игрока

Надёжный DayNightManager: структура и поэтому подход

Идея: менеджер хранит длительности дня и ночи, текущее состояние и отвечает за плавный переход цвета фона и проигрывание звуков. Мы используем Timer для отсчёта и SceneTreeTween (create_tween()) для интерполяции.

Создайте узел Node2D и прикрепите скрипт DayNightManager.gd:

extends Node2D

@export var day_duration: float = 30.0
@export var night_duration: float = 30.0
@export var transition_time: float = 2.0
@export var day_color: Color = Color(0.5, 0.5, 0.8)
@export var night_color: Color = Color(0.03, 0.03, 0.08)

var is_day: bool = true

@onready var timer: Timer = $DayNightTimer
@onready var background_rect: ColorRect = $BackgroundRect
@onready var daytime_sounds: AudioStreamPlayer2D = $DaytimeSounds
@onready var nighttime_sounds: AudioStreamPlayer2D = $NighttimeSounds

func _ready() -> void:
    # Настраиваем таймер и стартуем первый цикл
    timer.one_shot = true
    _apply_instant_state() # применим начальные визуалы
    timer.wait_time = day_duration if is_day else night_duration
    timer.start()

func _on_DayNightTimer_timeout() -> void:
    # Меняем состояние и запускаем плавный переход
    is_day = not is_day
    var target_color := day_color if is_day else night_color
    _start_transition(target_color)
    timer.wait_time = day_duration if is_day else night_duration
    timer.start()

func _start_transition(target_color: Color) -> void:
    # Плавно меняем цвет фона
    var tween := create_tween()
    tween.tween_property(background_rect, "color", target_color, transition_time).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
    # Переключаем звуки с небольшой задержкой, чтобы совпало с визуалом
    if is_day:
        nighttime_sounds.stop()
        daytime_sounds.play()
    else:
        daytime_sounds.stop()
        nighttime_sounds.play()

func _apply_instant_state() -> void:
    background_rect.color = day_color if is_day else night_color
    if is_day:
        nighttime_sounds.stop()
        daytime_sounds.play()
    else:
        daytime_sounds.stop()
        nighttime_sounds.play()

Важно: подключите сигнал timeout таймера к функции _on_DayNightTimer_timeout через редактор или кодом. Скрипт использует create_tween() — современный API Godot 4 для плавных анимаций.

Плавные переходы и дополнительные эффекты

  1. Интерполяция цвета: используйте tween для плавного изменения свойства ColorRect.color. Для более сложных палитр — храните массив ключевых цветов (рассвет, день, закат, ночь) и интерполируйте между ними.
  2. Освещение: добавьте Light2D в сцену и меняйте его energy/intensity во время перехода.
  3. Партиклы и анимации: при заходе солнца можно включать Particle2D (мерцающие огоньки), при рассвете — уменьшать их.
  4. Шейдеры: если нужны градиенты, звёзды или «голубой час», реализуйте shader_material для ColorRect (например, рисование звёзд с использованием UV и случайных семян).

Пример: плавное уменьшение интенсивности Light2D вместе с цветом фона:

@onready var sun_light: Light2D = $SunLight

func _start_transition(target_color: Color) -> void:
    var target_energy := 1.0 if is_day else 0.2
    var tween := create_tween()
    tween.tween_property(background_rect, "color", target_color, transition_time).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
    tween.tween_property(sun_light, "energy", target_energy, transition_time)
    if is_day:
        nighttime_sounds.stop()
        daytime_sounds.play()
    else:
        daytime_sounds.stop()
        nighttime_sounds.play()

Управление скоростью времени и режим отладки

  • Для тестирования удобно иметь множитель скорости времени: export var time_scale = 1.0. При старте таймера делайте timer.wait_time = (day_duration if is_day else night_duration) / time_scale.
  • Добавьте горячую клавишу для переключения состояния (например, F5 для мгновенного перехода) — это упрощает UX при тестировании.

Варианты визуализации — когда что выбрать

  • ColorRect: простой и быстрый способ для 2D. Хорош для большинства случаев.
  • Light2D + нормали: когда у вас локальные источники света и тени.
  • Шейдер для фонового неба: когда нужны звёзды, градиенты и динамические облака.
  • WorldEnvironment / Environment (для 3D): применяйте отдельно в 3D‑сценах.

Звуки: как добавить и синхронизировать

  • Два AudioStreamPlayer2D (или несколько дорожек) — для дня и ночи.
  • Можно перекрестно‑фейдить звуковые дорожки через tween_property(…, “volume_db”, …) для более мягкой смены.
  • Для атмосферы используйте лупы и отдельные SFX (сова, птицы). При желании добавьте Reverb/Bus на AudioServer для пространственного звучания.

Пример кроссфейда:

func _fade_sounds_to_day() -> void:
    var tween := create_tween()
    tween.tween_property(nighttime_sounds, "volume_db", -80.0, transition_time)
    tween.tween_property(daytime_sounds, "volume_db", 0.0, transition_time)

Усовершенствования и альтернативные подходы

  • Вместо Timer используйте глобальное «время мира» (game_time) и обновляйте состояние в _process(delta), тогда можно иметь произвольные кривые освещения.
  • Для реалистичного цикла добавьте промежуточные фазы (рассвет/закат) и отдельные настройки для каждой.
  • Если у вас сетевой режим — синхронизируйте состояние дня/ночи по серверу и отправляйте только метки времени.

Чек‑листы по ролям

Программист:

  • Реализовать DayNightManager с таймером.
  • Добавить плавные tween‑переходы для цвета и света.
  • Подключить звуки и настроить кроссфейды.
  • Добавить debug‑переключатель и масштаб времени.

Художник / аниматор:

  • Подготовить палитру цветов для рассвета, дня, заката, ночи.
  • Сделать отдельные слои неба/облаков для параллакса.
  • Подготовить спрайты/шейдер для звёзд и мерцания.

Дизайнер геймплея:

  • Определить механики, зависящие от времени суток (враги, торговцы, события).
  • Установить продолжительности фаз и правила спавна.
  • Проверить, как время суток влияет на уровень сложности.

Критерии приёмки

  1. При старте сцены BackgroundRect мгновенно соответствует текущему состоянию (день/ночь).
  2. По таймеру происходит смена состояния с плавным переходом цвета и параметров света не медленнее и не быстрее заданного transition_time (±10%).
  3. Звуки соответствуют фазе (днём — дневные треки, ночью — ночные); фейдинг не вызывает клипов.
  4. Отладочный переключатель позволяет форсировать состояния и менять time_scale без перезапуска.

Тесты и сценарии проверки

  • Тест 1: Стандартный цикл. Установить day_duration=5, night_duration=5, transition_time=1 — проверить, что цикл повторяется бесконечно и таймер каждый раз перезапускается.
  • Тест 2: Быстрое переключение. Нажать «форсировать ночь» и убедиться, что все визуальные и аудиоэффекты изменились.
  • Тест 3: Отключение звуков. Выключить AudioStreamPlayer2D и проверить, что отсутствие звуков не ломает логику.
  • Тест 4: Производительность. В сцене с 100 объектов проверить, нет ли падения FPS во время перехода.

Отладка: распространённые проблемы и решения

  • Проблема: цвета меняются рывками. Решение: убедитесь, что вы используете create_tween(), а не присваиваете color напрямую во фрейме.
  • Проблема: звуки обрезаются. Решение: используйте tween для volume_db или плавную остановку через fade‑out.
  • Проблема: таймер не срабатывает. Решение: проверьте, что timer.one_shot = true и сигнал timeout подключён; также проверьте, не стоит ли paused=true.

Мини‑методология внедрения (шаги)

  1. Создайте ColorRect и Timer в рабочей сцене.
  2. Добавьте DayNightManager и базовый код переключения.
  3. Настройте цвета и длительности; протестируйте в быстрых циклах.
  4. Добавьте звуки и Light2D, подключите tween‑переходы.
  5. Интегрируйте механики (спавн, ИИ), зависящие от времени суток.
  6. Проведите QA по чек‑листам и критериям приёмки.

Небольшой пример перехода с четырьмя фазами (рассвет/день/закат/ночь)

@export var palette: Array = [Color(0.15,0.05,0.1), Color(0.5,0.5,0.8), Color(1,0.6,0.4), Color(0.03,0.03,0.08)]
@export var phase_duration: float = 20.0
var phase_index: int = 0

func _on_DayNightTimer_timeout() -> void:
    phase_index = (phase_index + 1) % palette.size()
    var target_color := palette[phase_index]
    _start_transition(target_color)
    timer.wait_time = phase_duration
    timer.start()

Маленькая галерея крайних случаев (edge cases)

  • Проект с сетевым сервером: синхронизируйте только метку времени сервера.
  • Мобильные устройства: сократите частоту и сложность анимаций, экономьте батарею.
  • Большие уровни с несколькими камерами: убедитесь, что фон покрывает весь экран (используйте Control/Anchors или растянутый ColorRect).

Решающее дерево: как выбрать способ реализации

flowchart TD
    A[Требуется день-ночь?] -->|Нет| B[Не реализовать]
    A -->|Да| C[2D или 3D?]
    C -->|2D| D[ColorRect + Light2D]
    C -->|3D| E[WorldEnvironment + небо/шейдер]
    D --> F{Нужны звёзды и градиенты?}
    F -->|Да| G[Шейдер на ColorRect]
    F -->|Нет| H[Простая интерполяция цвета]
    E --> I[Настроить Environment и DirectionalLight]

Короткая памятка (cheat sheet)

  • create_tween().tween_property(node, “property”, value, time)
  • timer.one_shot = true; timer.start(seconds)
  • Color.linear_interpolate(other, t) — если хотите ручную интерполяцию
  • AudioStreamPlayer2D.play(), .stop(), свойство volume_db для фейдов

узел игрока на синем фоне в godot

Итог

Цикл день‑ночь — относительно простая механика, которая добавляет ощущение живого мира. Для 2D‑игры в Godot 4 оптимальным решением будет использование ColorRect для фона, Timer для отсчёта и create_tween() для плавных переходов. Добавив Light2D и звуковые дорожки, вы получите богатую атмосферную смену времени суток, которую легко расширять (рассвет, закат, звёзды, погодные эффекты) и интегрировать с игровыми механиками.

Важно: начните с простого прототипа, затем постепенно добавляйте визуальные и аудио‑слои, проверяя на производительность и UX.

Короткая версия для анонса: внедрите DayNightManager с таймером, ColorRect, Light2D и двумя AudioStreamPlayer2D — это даст вам полностью управляемую и расширяемую систему смены дня и ночи.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как проверить температуру GPU и что делать
Аппаратное обеспечение

Как проверить температуру GPU и что делать

Очистка жала паяльника: руководство и SOP
Ремонт

Очистка жала паяльника: руководство и SOP

Seahorse: шифрование файлов в Ubuntu
Security

Seahorse: шифрование файлов в Ubuntu

Бренд-стиль: руководство и шаблоны
Брендинг

Бренд-стиль: руководство и шаблоны

Разрешения камеры и микрофона в Firefox
Конфиденциальность

Разрешения камеры и микрофона в Firefox

Как выбрать вентиляторы для корпуса ПК
Аппаратное обеспечение

Как выбрать вентиляторы для корпуса ПК