Functions
CompilesA 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.
Declaring and calling
Section titled “Declaring and calling”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: eachname: type, separated by commas.-> floatsays what the function gives back. Leave it off when it gives back nothing.return valuehands 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.
Default and named arguments
Section titled “Default and named arguments”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}Kinds of function
Section titled “Kinds of function”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}Parameters without a type
Section titled “Parameters without a type”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.