Files
Overside srl 0ca80ae65b add rain sound
2026-02-24 18:55:34 +01:00
..
2026-02-03 11:26:48 +01:00
2026-02-24 18:55:34 +01:00
2026-02-24 18:55:34 +01:00
2026-02-16 07:19:27 +01:00
2026-02-24 18:55:34 +01:00
2026-02-24 18:55:34 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00
2026-02-03 11:26:48 +01:00

Dynamic Sky System for Godot 4.6

A stylized dynamic sky system with day/night cycles, weather, clouds, and VFX.

Setup Instructions

Step 1: Open Project in Godot

  1. Open your Godot 4.6 project
  2. Wait for the editor to import all scripts (check the bottom progress bar)
  3. If you see script errors, click Project > Reload Current Project

Step 2: Add to Your Scene

  1. Open the scene where you want the sky system
  2. Drag dynamic-sky/dynamic_sky.tscn into your scene tree
  3. Or right-click in the scene tree → Instance Child Scene → select dynamic_sky.tscn

Step 3: Configure the Environment

The DynamicSky node auto-creates required children. To link an existing environment:

  1. Select the DynamicSky node
  2. In the Inspector, under Environment:
    • Assign your existing WorldEnvironment node (or leave empty to auto-create)
    • Assign existing DirectionalLight3D for sun/moon (or leave empty)

Step 4: Generate Cloud Textures

Clouds need textures. Use the procedural generator:

# In a tool script or _ready():
var cloud_tex = ProceduralCloudTexture.create_default_cloud_texture(1)
$DynamicSky/CloudSystem.layer_configs[0].texture = cloud_tex

Or assign existing cloud textures to each CloudLayerConfig in the Inspector.

Step 5: Configure Shadow Texture

var shadow_tex = ProceduralCloudTexture.create_shadow_texture()
$DynamicSky/ShadowProxySystem.shadow_texture = shadow_tex

Testing the System

Test 1: Basic Scene Test

  1. Create a new 3D scene with a Camera3D and a MeshInstance3D (e.g., plane for ground)
  2. Instance dynamic_sky.tscn
  3. Run the scene (F5)
  4. You should see a gradient sky with sun light

Test 2: Time of Day

Add this script to test time changes:

extends Node

@onready var sky = $DynamicSky

func _ready():
	# Start at morning
	sky.set_time_of_day(0.25)

func _process(delta):
	# Press keys to change time
	if Input.is_action_just_pressed("ui_right"):
		sky.set_time_of_day(sky.get_time_of_day() + 0.05)
	if Input.is_action_just_pressed("ui_left"):
		sky.set_time_of_day(sky.get_time_of_day() - 0.05)
	
	# Print current time
	if Input.is_action_just_pressed("ui_accept"):
		print("Time: ", sky.get_time_of_day())

Test 3: Weather System

func _input(event):
	if event.is_action_pressed("ui_up"):
		$DynamicSky.set_weather(WeatherProfile.WeatherState.RAIN)
	if event.is_action_pressed("ui_down"):
		$DynamicSky.set_weather(WeatherProfile.WeatherState.CLEAR)

Test 4: Debug Panel

  1. Add a CanvasLayer to your scene
  2. Add a Control node as child
  3. Attach the sky_debug_panel.gd script
  4. In Inspector, assign the DynamicSky node to the dynamic_sky property
  5. Run and use the UI controls

Test 5: Meteor Shower

func _ready():
	# Ensure it's night for visibility
    $DynamicSky.set_time_of_day(0.0)
    # Wait a moment then trigger
    await get_tree().create_timer(1.0).timeout
    $DynamicSky.trigger_meteor_shower(30.0)

Test 6: Kill Volumes

  1. Add an Area3D to your scene
  2. Attach weather_kill_volume.gd script
  3. Configure the shape and size in Inspector
  4. Precipitation will be blocked inside this volume

Complete Test Scene Example

Create a new scene with this structure:

TestScene (Node3D)
├── DynamicSky (instance of dynamic_sky.tscn)
├── Camera3D
├── Ground (MeshInstance3D with PlaneMesh)
├── CanvasLayer
│   └── DebugPanel (Control with sky_debug_panel.gd)
└── TestScript (Node with test script below)

Test script:

extends Node

@onready var sky = $"../DynamicSky"

func _ready():
    # Generate cloud textures
    _setup_clouds()
    
    # Start at mid-morning
    sky.set_time_of_day(0.35)
    
    print("Dynamic Sky Test Ready!")
    print("Arrow keys: Change time")
    print("1-6: Change weather")
    print("M: Meteor shower")
    print("P: Pause/Resume time")

func _setup_clouds():
    var cloud_system = sky.cloud_system
    if cloud_system:
        for i in cloud_system.layer_configs.size():
            var tex = ProceduralCloudTexture.create_default_cloud_texture(i)
            cloud_system.layer_configs[i].texture = tex
        cloud_system.rebuild_layers()
    
    var shadow_system = sky.shadow_proxy_system
    if shadow_system:
        shadow_system.shadow_texture = ProceduralCloudTexture.create_shadow_texture()

func _input(event):
    if event is InputEventKey and event.pressed:
        match event.keycode:
            KEY_RIGHT:
                sky.set_time_of_day(wrapf(sky.get_time_of_day() + 0.02, 0, 1))
            KEY_LEFT:
                sky.set_time_of_day(wrapf(sky.get_time_of_day() - 0.02, 0, 1))
            KEY_1:
                sky.set_weather(WeatherProfile.WeatherState.CLEAR)
            KEY_2:
                sky.set_weather(WeatherProfile.WeatherState.CLOUDY)
            KEY_3:
                sky.set_weather(WeatherProfile.WeatherState.OVERCAST)
            KEY_4:
                sky.set_weather(WeatherProfile.WeatherState.RAIN)
            KEY_5:
                sky.set_weather(WeatherProfile.WeatherState.STORM)
            KEY_6:
                sky.set_weather(WeatherProfile.WeatherState.SNOW)
            KEY_M:
                sky.trigger_meteor_shower(30.0)
            KEY_P:
                if sky.day_night_controller.paused:
                    sky.resume_time()
                else:
                    sky.pause_time()

Troubleshooting

Issue Solution
Script errors on load Reload project: Project → Reload Current Project
No sky visible Ensure camera is looking up; check WorldEnvironment exists
Clouds not visible Assign textures to CloudLayerConfig or generate procedurally
Shadows not visible Assign shadow_texture to ShadowProxySystem
Stars not visible Set time to night (0.0 or 0.9+); check stars_visibility curve
Time not advancing Check paused is false on DayNightController
Weather not changing Check WeatherController has profiles; look at transition progress

Features

Preset Skybox Nodes

  • 6 presets: Clear Day, Sunset, Night, Overcast, Storm, Dawn
  • Runtime preset switching with smooth transitions
  • Non-destructive overrides

Day/Night Cycle

  • Configurable day length (1-1440 minutes)
  • Sun/moon arc movement
  • Color/intensity curves for sun, moon, ambient, fog
  • Star visibility at night
  • Time events (sunrise, sunset, noon)

Weather System

  • States: Clear, Cloudy, Overcast, Rain, Storm, Snow
  • Smooth transitions between states
  • Per-state cloud, wind, and VFX settings
  • Random or scripted weather timelines

2D Cloudscapes

  • 4 independent layers (low, mid, high, wisps)
  • Per-layer texture, tiling, opacity, color
  • Flow animation with wind influence
  • Evolution/morphing over time
  • Reactive to sun/moon lighting

Post-Processing

  • Sky gradient shading
  • Height and distance fog
  • Sun glow halo
  • Dawn/dusk enhancement
  • Procedural stars

VFX

  • Shooting stars (randomized)
  • Meteor showers (event-triggered)
  • Configurable appearance

Cloud Shadows

  • Projected shadow overlay
  • Syncs with cloud movement
  • Blur and opacity controls

Kill Volumes

  • Block precipitation in indoor areas
  • Box, sphere, cylinder shapes
  • Fade-out margins

Quick Start

  1. Add dynamic_sky.tscn to your scene
  2. Reference the DynamicSky node in your scripts
  3. Use the API:
# Get reference
@onready var sky = $DynamicSky

# Set time (0.0-1.0, where 0.5 = noon)
sky.set_time_of_day(0.5)

# Change weather
sky.set_weather(WeatherProfile.WeatherState.RAIN)

# Apply preset
sky.apply_preset("Sunset")

# Trigger meteor shower
sky.trigger_meteor_shower(60.0)

Debug Panel

Add SkyDebugPanel to your UI and assign the DynamicSky reference to see:

  • Current time and weather
  • Cloud coverage
  • Controls for testing

Resources

  • SkyConfig: Global sky parameters
  • SkyPreset: Complete preset configuration
  • WeatherProfile: Per-weather-state settings
  • CloudLayerConfig: Per-layer cloud settings
  • PostProcessProfile: Post-processing parameters

Performance

  • Disable unused cloud layers
  • Reduce cloud texture resolution
  • Lower VFX update rates
  • Disable shadow blur on low-end hardware