Changing scenes: transitions, preloading, loading screens
Transitions
Section titled “Transitions”Scene.change_scene("level_2") -- at onceScene.change_scene("level_2", {transition = "fade", duration = 0.4}) -- behind a fadeScene.change_scene("level_2", {transition = "circle", color = {1, 1, 1}})| Option | |
|---|---|
transition |
"fade", "wipe_left", "wipe_right", "wipe_up", "wipe_down", "circle" (an iris). |
duration |
Seconds for each half - covering, then uncovering (default 0.4). |
color |
{r, g, b} 0..1 (default black). |
loading |
A loading screen scene (below). |
min_time |
Seconds the loading screen stays at least (default 0.5). |
The screen is covered, the new scene switches in once its assets are
loaded, then it’s uncovered. Scene.is_transitioning() is true meanwhile
(ignore input, don’t start another change). The name can also be the
scene’s file ("scenes/level_2.scene.json", e.g. from a scene property).
Preloading
Section titled “Preloading”Start loading a scene’s assets before you need it, so the change is instant:
function Menu:ready() Scene.preload("level_1") -- while the player reads the menuend
function Menu:on_start_pressed() Scene.change_scene("level_1", {transition = "fade"})endScene.preload_progress("level_1") reports 0..1. Preloading finds the
scene’s textures (sprites, nine-slices, particles - any image a node
names), sounds, music and fonts, including those of the components it
uses.
Loading screens
Section titled “Loading screens”For big levels, show a scene of your own while the level loads - a progress bar, tips, an animation:
Scene.change_scene("world_2", {transition = "fade", loading = "loading", min_time = 0.8})- A fade into the loading scene.
world_2loads in the background.- When it’s loaded and the screen has been up for
min_time(so a fast load doesn’t just flash it), a fade intoworld_2.
Tutorial: a loading screen with a progress bar
Section titled “Tutorial: a loading screen with a progress bar”Create a scene loading (Scenes +), keep it light (no big textures -
it must appear quickly):
root├── Background (a ColorRect / TextureNode, or the scene background colour)├── Title (Text: "Loading...")├── Tip (Text)├── Bar (UI Progress Bar, 0..100)└── Loader (Node, scripts/loading.lua)-- scripts/loading.lua---@class Loading : ScriptInstanceBaselocal Loading = {}
local TIPS = {"Press Shift to dash", "Coins heal you a little", "Bosses have a weak spot"}
function Loading:ready() self.bar = Scene.find_node("Bar") Scene.find_node("Title").text = "Loading " .. (Scene.loading_target() or "") .. "..." Scene.find_node("Tip").text = TIPS[math.random(#TIPS)] self.shown = 0end
function Loading:update(dt) -- Ease the bar towards the real progress (it can jump in steps). self.shown = self.shown + (Scene.loading_progress() - self.shown) * math.min(1, dt * 8) self.bar.value = self.shown * 100end
return LoadingAdd the scene to the project’s scene list (it is, if you made it with
Scenes +). Then from anywhere:
Scene.change_scene("world_2", {transition = "fade", loading = "loading"})| Function | |
|---|---|
Scene.loading_progress() |
0..1: how far the scene behind the loading screen has loaded (1 when nothing loads). |
Scene.loading_target() |
That scene’s name (nil when nothing loads). |
How loading works (performance)
Section titled “How loading works (performance)”- Preloading walks the scene file once and queues each asset.
- Textures - usually most of the time - are read on the main thread
(packed
.rayzrgames read from one archive) and decoded on two worker threads (PNG decoding is the expensive part); finished images are uploaded to the GPU on the main thread, up to 4 a frame. The game keeps running smoothly - a loading screen can animate. - Sounds, music and fonts load on the main thread within a 4 ms budget a frame.
- Loaded assets are cached: the scene finds them when it loads, and the preload lets go of its references once the scene has its own.
- Threads only touch their own job’s memory; a preload that is cancelled while an image is decoding leaves the job to be freed when the worker finishes.
From Odin
Section titled “From Odin”Game_ChangeSceneWith(game, scene, .Fade, 0.4) // a transitionGame_ChangeSceneVia(game, scene, loadingScene, .Fade, 0.4, rl.BLACK, 0.8) // through a loading screenScene_PreloadBegin(game, scene)progress := Scene_PreloadProgress(game, scene)