Activity
An activity is a structured interaction the host game renders and the player completes. You declare a set of fields (each backed by a project variable), bundle related fields into groups when they should answer one question together, and the runtime hands the interaction to the host when an activity event fires. The host shows whatever UI fits the moment (a multiple-choice prompt, a quick-time event overlay, a minigame, a checklist), and the player’s input flows back into your project’s variables. Author activities in the editor’s Activities panel, then reference them through the activity event.
For conventions shared by all entity types, see Entities.
minigame-typed activity with four loose variable
bindings: one required bool, one required int, one optional string,
and one read-only bool.Fields
ID
The activity’s expression-namespace identifier. You’ll use this name to reference the activity on activity events and in any expression that queries activity state. Pick from the editor’s activity picker. Renaming the ID updates expressions that mention the old name.
Convention: activity ids are prefixed activity_ (e.g.
activity_lockpick, activity_pick_answer, activity_dodge_qte).
Name
The human-readable label shown for the activity in the editor’s activities table, the activity inspector, and any host UI that displays the activity’s title. Free-form string, author-typed. This is the visible label, not the expression-namespace ID. The host typically uses it as the on-screen heading: the multiple-choice question prompt, the minigame name, the quick-time event caption.
Type
Optional free-text label identifying how this activity is hooked up on
the host side. The runtime never inspects it; it’s a hint the
integrating studio reads when the activity event fires, to pick the
right engine-side handler (a Unity prefab key, a minigame id, a script
name). Use it when one StoryBonsai project drives several different
kinds of UI: tag a multiple-choice activity dialog, a quick-time event
qte, a minigame lockpick, and the host code branches on that label.
Free-form: pick whatever convention your engine team uses. Default is
empty.
Timeout
Optional integer time, in seconds, for the activity. When the host tracks the activity past this duration, the runtime treats it as out of time. The main use is quick-time events and minigames with a hard time limit. Leave empty for activities with no time limit.
Estimated duration
Optional float hint to the host about the expected duration of the activity, in seconds. Used for UI affordances such as progress bars and planning views. The runtime does not enforce or act on this value; it’s purely advisory for the host’s presentation layer.
Undo barrier
When true, completing this activity creates an undo barrier in save
state. The player cannot rewind past this point using undo or save-scene
restoration. Tick this for activities whose outcomes are meant to stick:
committed answers, final scores, irreversible quick-time failures.
Default is false.
Players
Multiplayer scope. A list of player input slot ids that this activity applies to. The Players row only shows up when the project is set to more than one player. An empty list means the activity applies to all players. When non-empty, only the listed players are participants; the runtime gates activity events and variable overrides to those slots. Default is an empty list (all players).
Variables
The fields the activity exposes. The Variables section lists every project variable bound to the activity; variables that are also members of a group render inside the group instead, so this section’s count reflects the loose (ungrouped) bindings.
Each entry binds one project variable to a field on the activity and configures how the field behaves on completion:
- Kind badge: the variable’s type (
bool,int,decimal,string,list), sourced from the project Variable. Read-only here; change the type from the Variables data panel. - Effect: what the activity does to the variable when it completes.
- Replace value: overwrite the variable with whatever the player provided. The standard mode for multiple-choice answers and quick-time success flags.
- Increment value: add the player’s value to the current value.
Numeric kinds (
int,decimal) only. The standard mode for minigame scores that accumulate across multiple firings. Requires a Default (the editor snaps it to0if you clear it). - Read-only: show the current value for context but never write it. Use this when the player needs to see a number (current health, current score) while answering an unrelated question. Default, Bounds, and Required are hidden in this mode.
- Default: the value the activity writes when the player makes no
input. Kind-aware editor (a checkbox for
bool, a number field for numerics, a string field forstring/list). A Reset link next to the field clears the default in Replace mode (with no default, the variable keeps whatever value it had when the activity started, and no write happens). Per-firing overrides on the activity event can replace this value for a single firing. - Bounds (min / max): optional numeric bounds clamped by the
runtime when the activity writes to the variable. Shown for
intanddecimalkinds. Empty fields mean no bound on that side. - Required: when ticked, the host cannot complete the activity
until the variable has a non-default value. Use it on any field
whose outcome later nodes branch on. Stored on disk as
mandatory. - Delete variable: removes the binding from the activity. The underlying project variable is not deleted; clear it from the Variables data panel if you want it gone everywhere.
See Variable for the shape of the bound variables.
Variable groups
A group bundles several bool bindings into one logical answer and
enforces how many of them must be true when the activity completes.
Reach for groups when one question maps to a set of mutually exclusive
choices (a single-select radio) or to a small fixed subset (pick any
two of five). Use loose bindings for everything else.
Each group has:
- Name: human-readable label shown in the inspector, in validator
messages, and (for the runtime view) on the host side. Stored on
disk as
id. - Selection bounds: min and max, the inclusive count of
members that may be true when the activity completes. A preset chip
next to the bounds names the common shapes (
Exactly N,At most N,At least N,Between N and M, orNo constraintwhen both bounds are open) so you don’t have to read the numbers to know what the group enforces. Empty max means no upper bound. Invalid bounds (negative min, max < min, min or max greater than the member count) surface inline as a red error under the bounds row. - Members: the
boolvariables in the group. The member picker reaches across everyboolvariable in the project. Picking a variable attaches it on the fly if it isn’t already on the activity, and either way its binding is snapped to the group shape (Effect = Replace value, Default =false, Required ticked) so the group can enforce its bounds cleanly. Removing the last member deletes the group rather than leaving a husk with no rule to enforce.
Translator notes
Name can carry a translator note: see Entities for more information.
How the runtime pauses for the activity
An activity event is a synchronous cut in the flow. When the runtime reaches the event during a commit, it queues the activity, pauses, and returns control before running anything downstream: no more events on the same node, no scene Update, no On exhausted node, no new choice set. The host takes over from there, and nothing else in the story advances until the player finishes.
When the player finishes and the host completes the activity, the runtime resumes the same commit against the new variable values. Any event authored after the activity on the same node, a Set variable, a Jump gated on the activity’s output, a Complete project, sees the player’s answer at the moment it fires. That guarantee is what lets a Jump right after the activity branch on what the player just chose. Without it, activities followed by conditional flow would silently misfire.
Activities surface strictly one at a time. If a node holds two activities, or the first activity’s continuation lands on another activity, the second one arrives after the first has completed, not alongside it. Undo works at the commit boundary: rewinding a completed activity lands at the point before the choice that triggered it, not somewhere between the pause and the resume.
See the Activity event page for the event-side view and the pause signal the host reads.
When to reach for activities
An activity is the right shape when a moment of dialogue needs a structured pause: a multiple-choice prompt, a quick-time event, a scored minigame, a slider, a checklist. The runtime hands the activity to the host when an activity event fires; the host renders whatever fits the moment and writes the player’s input back into the project variables you bound under Variables. While the host has the activity, the flow of logic pauses; when the player finishes, the runtime resumes using the new variable values as it goes. Reach for an activity instead of a chain of choice nodes when you want the host’s UI to take over for a beat rather than the dialogue flow.
The Variables list is where the activity’s shape lives: each binding picks a project variable, sets its effect (replace, increment, read-only), and optionally caps it with bounds or marks it required. Per-firing overrides on the activity event let one activity definition serve many contexts (different defaults, different bounds), so reach for an event-side override before reaching for a new activity when the only thing changing is a value.
Reach for a group when one question writes to several bool
variables at once and the count of selected members is part of the
contract. A “pick exactly one suspect” group is three booleans plus
min: 1, max: 1; a “circle up to two pressure tactics” group is six
booleans plus min: 0, max: 2. The runtime enforces the bounds at
completion, so downstream nodes can branch on the variables without
defensively checking that the player picked the right number.
See also
- Activities: the authoring walkthrough for building an activity end to end.
- Activity event: the event that starts an activity.
- Variable: activities bind to project variables via their Variables list.
- Expressions: id conventions.