Skip to main content

Rive Scripting Quick Reference

Node Script Skeleton

--!strict

export type MyNode = {
speed: Input<number>,
enabled: Input<boolean>,
path: Path,
paint: Paint,
}

function init(self: MyNode): boolean
return true
end

function update(self: MyNode)
end

function advance(self: MyNode, seconds: number): boolean
return true
end

function draw(self: MyNode, renderer: Renderer)
end

return function(): Node<MyNode>
return {
init = init,
update = update,
advance = advance,
draw = draw,
speed = 1,
enabled = true,
path = Path.new(),
paint = Paint.new(),
}
end

Lifecycle Order

  1. init(self, context) - once on start
  2. update(self) - when inputs change (NO context param!)
  3. advance(self, seconds) - every animation frame
  4. draw(self, renderer) - on canvas repaint (keep pure, no state changes!)

Inputs & Data Binding

Define Inputs

export type MyNode = {
size: Input<number>,
tint: Input<Color>,
model: Input<Data.Character>,
enemy: Input<Artboard<Data.Enemy>>,
}

return function(): Node<MyNode>
return {
init = init,
draw = draw,
size = 80,
tint = Color.rgb(255, 120, 80),
model = late(),
enemy = late(),
}
end

Read Input Values

local value = self.size
self.tint -- Color

ViewModel and Artboard Inputs

-- ViewModel inputs expose Property<T> fields that use .value
self.model.health.value
self.enemy:instance()

ViewModel Access (Main Artboard)

function init(self: MyNode, context: Context): boolean
local vm = context:viewModel()
local score = vm and vm:getNumber("score")
if score then
print(score.value)
end
return true
end

Drawing Essentials

Path

local path = Path.new()
path:moveTo(Vector.xy(0, 0))
path:lineTo(Vector.xy(100, 0))
path:lineTo(Vector.xy(100, 100))
path:close()

Paint

local fill = Paint.with({ style = "fill", color = Color.rgb(80, 170, 255) })
local stroke = Paint.with({ style = "stroke", thickness = 4, color = Color.rgb(30, 60, 120) })

Renderer

renderer:drawPath(path, fill)
renderer:save()
renderer:transform(Mat2D.withTranslation(50, 0))
renderer:drawPath(path, stroke)
renderer:restore()

Luau Essentials Used in Rive

Strict Mode

--!strict

Tables (Arrays + Dictionaries)

local list = {1, 2, 3}
local dict = {x = 10, y = 20}
for i, v in ipairs(list) do end
for k, v in pairs(dict) do end

Functions and Methods

local function clamp(value: number, min: number, max: number): number
return math.max(min, math.min(max, value))
end

function MyType:methodName()
end

String Interpolation

print(`Score: {score}`)

Next Steps