Script Types Overview
Rive provides 6 script types, each designed for a specific purpose. This page gives you the big picture — which script type to choose and when.
If you haven't read How Rive Scripts Work yet, start there first. It explains WHY scripts have the structure they do — the "protocol" concept, factory functions, and lifecycle callbacks.
The 6 Script Types
| Script Type | Primary Purpose | Attach To |
|---|---|---|
| Node Script | Animation logic, custom rendering | Any node |
| Layout Script | Custom layout behavior | Layout components |
| Converter Script | Data transformation for bindings | Data bindings |
| Path Effect Script | Modify path geometry | Strokes |
| Util Script | Shared code libraries | Nothing (imported) |
| Test Script | Unit testing Util Scripts | Nothing (run manually) |
Listener<T> is a function signature, not a script type. See Listeners for details.
Node Script
Use when: You need animation logic, custom drawing, or interactive behavior on a node.
Key features:
- Lifecycle callbacks:
init,update,advance,draw - Pointer event handlers:
pointerDown,pointerMove,pointerUp - Access to Renderer for custom drawing
- Can have inputs from the editor
Typical use cases:
- Procedural animations (particles, physics)
- Custom drawing (graphs, visualizations)
- Interactive elements (buttons, sliders)
- Game logic (collision, scoring)
Factory return type: Node<T>
return function(): Node<MyScript>
return { init = init, advance = advance, draw = draw }
end
Learn more: Node Script Protocol → | Node Lifecycle →
Layout Script
Use when: You need programmatic control over how child elements are positioned and sized within a Layout component.
Key features:
- All Node Script lifecycle callbacks PLUS:
measure()- Propose ideal size (for "Hug" fit type)resize(size)- React to size changes, position children
Typical use cases:
- Masonry grids
- Carousels with custom spacing
- Responsive layouts with breakpoint logic
- Data-driven layout systems
Factory return type: Layout<T>
return function(): Layout<MyLayout>
return { init = init, measure = measure, resize = resize, draw = draw }
end
Learn more: Layout Script Protocol →
Converter Script
Use when: You need to transform data between a source and target in data bindings.
Key features:
convert(input)- Transform source → targetreverseConvert(input)- Transform target → source (for two-way binding)- Works with DataValue types (Number, String, Boolean, Color)
Typical use cases:
- Format numbers (add units, decimals)
- Temperature conversion (Celsius ↔ Fahrenheit)
- Color transformations
- String formatting/parsing
Factory return type: Converter<T, InputType, OutputType>
return function(): Converter<MyConverter, DataValueNumber, DataValueString>
return { convert = convert, reverseConvert = reverseConvert }
end
Learn more: Converter Script Protocol →
Path Effect Script
Use when: You need to modify the geometry of a path in real-time (stroke effects, distortions).
Key features:
update(inPath)- Receives original PathData, returns modified PathDataadvance(seconds)- Optional frame updates for animated effects- Access to PathCommand iteration
Typical use cases:
- Wave/wobble distortion effects
- Custom dash patterns
- Procedural path generation
- Animated stroke effects
Factory return type: PathEffect<T>
return function(): PathEffect<MyEffect>
return { init = init, update = update, advance = advance }
end
Learn more: Path Effect Script Protocol →
Util Script
Use when: You have shared code (math functions, constants, helpers) used by multiple scripts.
In the Rive editor, select Blank Script from the script type dropdown. There is no dedicated "Util Script" option—you create one by selecting Blank Script and following the Util Script pattern described below and in the official Rive docs.
Key features:
- No lifecycle callbacks — just a module table
- Imported with
require("UtilName") - Runs once when first required (cached)
- Perfect for pure functions and constants
Typical use cases:
- Math utilities (lerp, clamp, easing functions)
- Color palettes and constants
- Helper functions shared across scripts
- Configuration objects
Return type: Module table (not a factory)
local MathUtils = {}
function MathUtils.lerp(a: number, b: number, t: number): number
return a + (b - a) * t
end
return MathUtils
Learn more: Util Script Protocol →
Event Listening (Not a Script Type)
Listener<T> is NOT a Script TypeListener<T> is a function signature for addListener()/removeListener() methods, not a script return type.
To handle events in Rive, use these patterns:
1. ViewModel Property Listeners (in Node scripts):
function init(self: MyNode, context: Context): boolean
local vm = context:viewModel()
local score = vm:getNumber("score")
if score then
score:addListener(function()
print("Score changed to: " .. score.value)
end)
end
return true
end
2. Pointer Events (in Node scripts):
function pointerDown(self: MyNode, event: PointerEvent)
print("Clicked at: " .. event.position.x)
end
Learn more: Listeners →
Test Script
Use when: You want to write unit tests for your Util Scripts.
Key features:
setup(test: Tester)- Define test casestest.case(name, fn)- Individual testtest.group(name, fn)- Group related testsexpect(value).is(expected)- Assertions
Typical use cases:
- Verify math utilities work correctly
- Test edge cases in helper functions
- Regression testing after changes
- Document expected behavior
Return type: Tests (function)
local MathUtils = require('MathUtils')
function setup(test: Tester)
test.case('lerp at 0.5', function(expect)
expect(MathUtils.lerp(0, 100, 0.5)).is(50)
end)
end
return function(): Tests
return setup
end
Learn more: Test Script Protocol →
Scripts and State Machines
Rive state machines decide what state an animation is in. Scripts decide how that state is visualized or extended.
How they connect:
- Inputs are the bridge. Bind state machine inputs to script inputs or ViewModel properties.
- Property listeners (
addListener()) respond to ViewModel property changes triggered by state machines. - Node scripts render visuals and can read inputs or ViewModel values to drive drawing.
Typical flow:
- State machine updates an Input (e.g.,
isHovering = true) - Script reads that input in
update()oradvance() - Script changes visuals in
draw()or updates ViewModel data
If you need to react to property changes, use property:addListener() in a Node script. If you need to render or animate based on inputs, use update() or advance() callbacks.
Quick Decision Guide
Factory Functions Recap
Remember from Part 1: every script (except Util and Test) uses a factory function. The factory creates fresh instances so each object using your script gets its own data.
| Script Type | Factory Return |
|---|---|
| Node | Node<T> |
| Layout | Layout<T> |
| Converter | Converter<T, In, Out> |
| Path Effect | PathEffect<T> |
| Listener | Listener<T> |
| Util | Module table (no factory) |
| Test | Tests function (no factory) |
Next Steps
- Continue to Inputs and Data Binding
- Need a refresher? Review Quick Reference