studio
FolioTier 1
transition
Blend or fade into every change inside the block at once.
Use a transition block to blend several stage changes together. Put background changes, sprite events, and any accompanying audio or variable changes under transition dissolve: or transition fade:, indented by two spaces. Only events inside the block share its blend.
The story waits for the block to finish by default. Turn off Wait for it to finish in the header Inspector, or add wait=false inside the header call, to let the next event begin during the blend. The block controls waiting for its children.
The body accepts background, sprite, variable, and audio changes, plus when branches containing those changes. Reader interactions, routing, video, and nested transition blocks cannot go inside. Children have no transition clauses or animated moves of their own.
For a single background change outside a block, use bg with fade or dissolve. Its transition continues by default; add wait=true inside that inline call to wait for it. This waits for the blend, not for video-backed background playback.
Set a duration to control the pacing, or give fade a color to pass through. An empty dissolve leaves the picture unchanged, while an empty fade blinks through its color. Forge offers an Empty transition / Add a step placeholder for either. The supported names are dissolve and fade, with fadein accepted as an alias.
Parameters
| Parameter | Kind | Required | Default | Notes |
|---|---|---|---|---|
| name | identifier | yes | - | The blend the block plays, written as a call on the header line. The set is closed: `dissolve` and `fade` are the only two names this verb spells, and anything else is a hard error that blocks the save - there is no custom-transition escape hatch. `dissolve` takes an optional crossfade duration - `transition dissolve(0.8):` is 0.8s, and any decimal is legal (`dissolve(0.83)`); bare `dissolve` = the 0.5s registry default. `fade` is `fade(seconds, color=#rrggbb)`; bare `fade` = the defaults (1s, black), split half out and half back in. `fadein` is a parse alias of `fade`. Legacy spellings like `dissolve-d8` no longer parse; write the call form. Imported Ren'Py transitions that map to a non-transition catalog entry arrive as that entry's own effect line, not as a transition: `vpunch`/`hpunch` become `@punch`, and the directional / spatial family (`pixellate`, `wipe*`, `slide*`, `iris*`, ...) approximates to a dissolve. |
| body | identifier | no | - | The indented lines under the header - every change the one blend plays over, two spaces in, like a `when` body. A body holds stage changes only: `bg`, every `sprite` verb, `set`, audio (`music` / `sound` / stop / volume), and a `when` whose branches hold only those. Dialogue, `narrate`, `choice`, `pause`, `jump` / `call` / `return` / `end`, video, paywall, input, and another `transition` are errors that block the save. A child never carries its own ` with ...` clause or a non-teleport move - the block plays it. An empty body is legal without a warning for both names: `fade` blinks, while `dissolve` leaves the picture unchanged and keeps its duration and wait setting. Forge shows an Empty transition / Add a step placeholder until the body has a step. Anything changed at the same moment but OUTSIDE the block cuts. |
| wait | boolean | no | true | Whether the story holds until the block's blend finishes. Default on; write `wait=false` inside the header call to let the next event run during the blend. In Forge this is the header Inspector's "Wait for it to finish" switch. The block controls waiting for its body, and children cannot carry their own transition clauses. Outside a block, a `bg` inline transition also accepts `wait`, but defaults to off; use `wait=true` there to opt in. |
Canonical example
transition dissolve(0.8):
bg bg-kitchen-morning
sprite show emma
sprite show noahscene bg kitchen_morning
show emma happy
show noah
with Dissolve(0.8)transition is a container: a header carrying one blend and a
trailing colon, then an indented body of the changes that blend plays
over. It is the screenplay's DISSOLVE TO: / FADE TO: - the body is
what you dissolve or fade to. A change carries its own transition; a
transition block carries one transition for every change inside it.
Notes
One change does not need a block. Put the transition on the line
itself - bg bg-kitchen-morning with dissolve(0.5), sprite show emma with fade - and it plays for that change alone. Reach for the block
when a backdrop swap and the sprites around it have to land together,
or when the whole frame should go through black.
What blends and what cuts. Only what is inside the body is in scope. A sprite shown on the line above the header, outside the block, cuts in at full opacity while the body blends around it. That is the point of the container: the scope is what you indented, not "whatever happened recently".
Dissolve is a cross-fade; fade goes through a color. dissolve
holds the old frame and brings the new one up through it. fade splits
its duration in half: out to the color over the first half, the body
applies under the opaque wash, then back in over the second half - the
whole frame, sprites included. Empty bodies are valid without a warning.
An empty fade body is a blink; an empty dissolve leaves the picture
unchanged and keeps its duration and wait setting. Forge shows an
Empty transition / Add a step placeholder for either kind. Select it
to add a stage change inside the block.
The block waits by default. Turn off Wait for it to finish in the
header Inspector, or write wait=false inside the header call, to let the
next event run during the blend. The block controls waiting for its body;
children have no transition clause or wait switch of their own. An inline
bg transition outside a block continues by default and accepts wait=true
to opt in.
transition fade(1.2, color=#000000) if act_two:
sprite hide emma
bg bg-station-night
Coming from Ren'Py. A standalone with dissolve / with fade line
imports as this block, wrapping the changes pending since the last
interaction, which is Ren'Py's own rule. $ renpy.transition(x) wraps
the changes that follow it instead. with None stays a cut. An inline
with on a single statement stays that statement's own clause.