Skip to content

Functions

Compiles

A function is a named piece of code you can run from elsewhere. Functions keep events short, give a name to an idea (“find the player”, “is it cooled down?”) and let you reuse code instead of copying it.

fn distance_between(a: Entity, b: Entity) -> float {
let from: vec3 = $entity.get_world_position($support.entity_get_component(a, "transform.vscript"))
let to: vec3 = $entity.get_world_position($support.entity_get_component(b, "transform.vscript"))
return $math.distance(from, to)
}
fn report(other: Entity) {
let far: float = distance_between($entity.get(), other)
$debug.print_line("{} is {} away", [$entity.get_name(other), far], false)
}
  • fn, then the name, then the parameters in parentheses: each name: type, separated by commas.
  • -> float says what the function gives back. Leave it off when it gives back nothing.
  • return value hands the answer back and ends the function.

Call a function by name with its arguments in the same order. A function may call one declared further down the file.

A parameter can have a default, used when the call leaves it out. Arguments can also be given by name, in any order, which makes calls with several numbers much easier to read:

fn scaled(value: int, scale: int = 10, offset: int = 0) -> int {
return value * scale + offset
}
fn examples() {
let a: int = scaled(2) // scale 10, offset 0
let b: int = scaled(2, 3) // scale 3
let c: int = scaled(2, offset: 5) // scale 10, offset 5
}

The words in front of fn say who may call it and how it behaves. Most functions have none.

Written Means Use it for
fn A helper; only this script calls it. Most of your code.
event export fn Called from outside by name: by the engine, or by another script. Reacting to things; see Lifecycle and events.
export fn Callable from outside, but not an event. Rare in your own scripts.
const fn Promises not to change any field. Questions: “is it cooled down?”, “where is the player?”
virtual fn A script that inherits this one may replace it. Hooks for child scripts.
override fn Replaces the parent’s virtual function. Changing inherited behaviour; see Inheritance.

Words combine: shipped scripts are full of virtual const fn and override const fn.

// Only answers a question, never changes state.
const fn is_ready(now_ms: int, last_ms: int, wait_ms: int) -> bool {
return now_ms - last_ms >= wait_ms
}

A parameter written without a type accepts any value. Events are often written that way, because the engine decides what it sends:

event export fn trigger_overlapped(other, unused) {
if !other {
return
}
}

Name the parameters after what they are (other, field, previous), even if you ignore them.

For programmers

Today’s compiler is lenient about three promises it doesn’t yet check: that a const fn writes no fields, that every path of a function with a return type returns, and that a function without one returns nothing. Keep them anyway; the engine’s own compiler enforced all three. Functions are statically dispatched unless virtual/override; there are no function values, closures or overloading. Recursion compiles but has no tail-call story; prefer loops.