FolioTier 1
say
Attribute a dialogue line to a named character.
say puts a line of dialogue on screen and attributes it to a named speaker. You reach for it whenever a character in your scene speaks - it is the primary tool for carrying conversation forward and the construct your script will use most.
The choice between a cast handle and a quoted name is a maintenance decision, not a style one. Use a cast handle for any recurring character so that a rename in your cast sheet propagates automatically everywhere that character speaks. Reserve the quoted form for incidental voices that genuinely do not belong in your cast, such as an unnamed bystander or a background announcement.
Each say is one beat of dialogue. You cannot split a single character's speech across continuation lines - start a fresh say for each new line of text instead, as shown in the canonical example above.
If you want words on screen with no speaker at all, that is the job of narrate, not say with an empty string. Mixing them up leaves an empty namebox visible rather than hiding it entirely.
The optional color on a quoted speaker applies only to the namebox for that individual line. It does not carry forward to other say statements using the same quoted name elsewhere in the script, so if you find yourself repeating the same name and color, that character probably belongs in the cast.
Parameters
| Parameter | Kind | Required | Default | Notes |
|---|---|---|---|---|
| character | string | yes | - | The speaker. A bare cast handle (`say vee:`) references a cast member by a stable id and is rename-safe - renaming the character never touches the line. A quoted name (`say "Guard":`) is a one-off custom speaker that is not in the cast, optionally followed by a `#rrggbb` namebox color (`say "Guard" #8899ff:`). The colon separator is required. For a line with no speaker, use `narrate` instead. |
| text | string | yes | - | The dialogue line. Supports text-tag grammar (see Effects → text-tags). Each `say` is one logical line - implicit string continuation across indentation changes inside a label body is not supported. |
Canonical example
say "Emma": "I missed you."
say "Emma": "How long has it been?"e "I missed you."
e "How long has it been?"The Folio shape mirrors Ren'Py's character-attributed dialogue line
verbatim: a Character reference followed by a quoted string. The
importer's deterministic pass handles every variation of the Ren'Py
shape - short-form character aliases (e "..."), interpolation
("Hello, [player_name]"), and the inline what-extension
(e "Hello," (what="…")) - so creators rarely need to think about
the lowering.
Notes
say is the most-used construct across the Ren'Py corpus by an order
of magnitude - it appears thousands of times in a typical full-size
game. It carries the burden of getting style
right - text-tag grammar ({b}, {i}, {color}, {wave},
{vibrate}), voice-line auto-attachment, and per-character text
styling all hang off this verb.
The speaker is either a bare cast handle (say vee:), which points at
a cast member by a stable id and survives a rename, or a quoted one-off
name (say "Guard":) with an optional #rrggbb namebox color. The importer translates Ren'Py character aliases into
display names by reading the Character() definition.
A line without a leading character identifier is not a say -
it's a narrate. The two are deliberately separate so the importer,
the runtime, and the node editor can render narrator lines with their
own visual treatment (no namebox, full-width text). When in doubt,
write narrate "…" rather than say "…".
See also
narrate- narrator lines without a character attributioncharacters- defining the characters this verb referencestext-tags- inline formatting grammar