The Secret Sauce of Shadows: Mastering SkyLight
The Secret Sauce of Shadows: Mastering SkyLight
Ever wonder why some Fortnite islands look like a high-budget cutscene while yours looks like it was rendered on a toaster? It’s usually not the models; it’s the light bouncing around. Specifically, it’s the SkyLight. Think of it as the invisible "fill" that stops your shadows from looking like pitch-black voids. If you want your island to pop with realistic (or stylized) color without turning your players' GPUs into fireworks, you need to master this one component.
What You'll Learn
- What SkyLight actually is (and why it’s not just "the sky").
- How Global Illumination works using the analogy of paint splatter.
- The difference between Real-Time Capture and Cubemaps (and why your low-end console players will thank you).
- How to tweak Intensity and Color to set the mood, from sunny day to spooky horror.
How It Works
The "Paint Splatter" Analogy
You know how sunlight hits a rock in the Grand Canyon, but the side facing away from the sun isn’t pitch black? It’s still visible, right? That’s because light bounces off the red rocks, splatters onto your white shirt, and bounces back onto your face. That bounced light is Global Illumination.
In Fortnite/UEFN, the SkyLight component is the engine that calculates this bounce. It doesn’t create the primary light (that’s the Directional Light, aka the Sun/Moon). Instead, it acts as the Fill Light.
Real-Time Capture vs. Cubemaps
This is where things get technical, but stick with me.
- Real-Time Capture: Imagine a camera spinning around your island, taking a photo of every single pixel, every color, and every reflection, 60 times a second. This is incredibly accurate. If a player moves a red crate, the light bouncing off it updates instantly. It looks amazing, but it’s heavy. It’s like playing a 4K movie on a potato phone—it’ll lag.
- Cubemap (The "Snapshot"): Instead of taking a video, the game takes one static photo of the environment’s lighting. It’s like a pre-rendered background. It’s super fast and works on low-end devices, but if you move a giant red wall, the lighting won’t change until you reload or update the map.
The Sweet Spot: Most starter islands use a hybrid. They enable Real-Time Capture for the main look but load a Cubemap as a backup for lower-end devices so the game doesn’t crash.
Intensity and Color
- Intensity: This is the volume knob for bounced light. Low intensity = deep, dramatic shadows (horror game vibes). High intensity = flat, bright, cartoon vibes (Battle Royale vibes).
- Color: This tints the bounced light. Want a zombie apocalypse? Tint the SkyLight green. Want a sunset romance? Tint it orange. It colors the shadows.
Let's Build It
We aren’t just tweaking settings in the menu; we’re going to make a Dynamic Mood Switcher. We’ll create a trigger that, when a player steps on it, changes the SkyLight’s color and intensity to simulate a sudden "storm front" passing over.
This requires a Verse Script attached to a Trigger Volume.
The Setup
- Place a Trigger Volume (a box that detects when players enter).
- Find your SkyLight component in the World Outliner. Note its name (e.g.,
SkyLight_1). - Create a new Verse file and attach it to the Trigger Volume.
The Verse Code
# We need to import the basic frameworks for Verse and World simulation
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
# This is our main device script.
# It "listens" for events from the Trigger Volume.
script class StormTriggerDevice extends Device:
# 1. VARIABLES: The "Loot Slots" for our data
# We need a variable to store the "new" color we want to apply.
# Think of this as a "Mood" card we draw from the deck.
new_storm_color: vector3 = <0.2, 0.3, 0.5> # A dark, stormy blue-grey
# We also need a variable for the new intensity.
# This is like the "Volume" slider for the bounced light.
new_intensity: float = 0.5 # Half as bright as the default sunny sky
# 2. EVENTS: The "Trigger" moment
# This function runs automatically when a player enters the volume.
# It's like the "Elimination" event firing when someone gets knocked out.
OnBegin<override>()<suspends>: void =
# Wait for a player to enter the trigger
for player : GetPlayers():
# If the player is inside, we change the lighting
ApplyStormMood()
# 3. FUNCTIONS: The "Action"
# This is the code that actually does the work.
# Think of this as the "Building Edit" command.
ApplyStormMood(): void =
# We need to find the SkyLight component in the world.
# In Verse, we use 'Find' to grab a component by name.
# It's like finding your favorite gun in the loot pool.
if sky_light := FindComponent<LightComponent>("SkyLight_1"):
# NOW WE CHANGE THE LIGHTING
# .SetIntensity() is the command to change the volume knob.
sky_light.SetIntensity(new_intensity)
# .SetColor() is the command to change the tint.
# We pass in our vector3 (R, G, B) values.
sky_light.SetColor(new_storm_color)
# Optional: Log a message so we know it worked
Print("Storm front arrived! Lighting updated.")
Walkthrough: What Just Happened?
script class StormTriggerDevice: This declares that we are building a new device behavior. It’s like defining the rules of a new game mode.new_storm_color: vector3: This is a Variable. In Fortnite terms, a variable is a loot slot that can hold different items. Here, it holds a color (Red, Green, Blue values). We set it to a dark blue-grey.OnBegin: This is an Event. An event is something that happens to the device.OnBeginhappens when the game starts or the player enters the trigger zone. It’s the "Battle Bus Door Opens" moment.FindComponent<LightComponent>: This is how we reach into the game world and grab the SkyLight. We’re telling Verse: "Go find the component named 'SkyLight_1' that handles light."SetIntensity&SetColor: These are Functions. A function is a command you give to an object.SetIntensityturns the volume knob.SetColorchanges the tint.
Try It Yourself
Challenge: The current code makes the storm dark and blue. Can you make a "Golden Hour" switch?
- Create a second Trigger Volume.
- Change the
new_storm_colorto a warm orange/yellow (try<1.0, 0.6, 0.2>). - Increase the
new_intensityto1.5(brighter than default). - Make sure the script listens to the new trigger.
Hint: You can have multiple variables in one script! Just define sunset_color and sunset_intensity alongside your storm variables, and use an if statement to check which trigger fired. Or, simpler: just make two separate scripts, one for Storm and one for Sunset.
Recap
- SkyLight is the Fill Light. It handles the bounced light and shadows, not the direct sun.
- Global Illumination is the fancy term for light bouncing off surfaces (like paint splatter).
- Real-Time Capture is accurate but heavy; Cubemaps are fast but static.
- In Verse, you can control SkyLight Intensity and Color using
SetIntensity()andSetColor()on theLightComponent.
Now go make your island look less like a dimly lit basement and more like a next-gen masterpiece.
References
- https://dev.epicgames.com/documentation/en-us/fortnite/lighting-and-lumen-quick-start-guide-in-unreal-editor-for-fortnite
- https://dev.epicgames.com/documentation/en-us/fortnite/lighting-starter-island-template-in-unreal-editor-for-fortnite
- https://dev.epicgames.com/documentation/en-us/fortnite/using-day-sequence-devices-in-unreal-editor-for-fortnite
- https://dev.epicgames.com/documentation/en-us/fortnite/tmnt-city-starter-visual-styles-in-unreal-editor-for-fortnite
- https://dev.epicgames.com/documentation/en-us/uefn/UE/building-virtual-worlds/lighting-and-shadows/light-types-and-mobility/SkyLight
Verse source files
- 01-fragment.verse · fragment
Turn this into a guided course
Add SkyLight to your free study plan — we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.
References
Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.