Types
CompilesEvery value has a type that says what kind of thing it is. You write a type after a colon when you declare something:
let lives: int = 3let speed: float = 2.5let title: string = "Knockout City"Plain values
Section titled “Plain values”| Type | Holds | Example |
|---|---|---|
int |
A whole number, positive or negative. | 3, -100, 0xFF |
float |
A number with a fractional part. | 2.5, 0.016 |
bool |
true or false. |
true |
string |
Text. | "Welcome!" |
Convert between int and float with as:
let seconds: float = 2.75let whole: int = seconds as intlet back: float = whole as floatTo choose how a float becomes an int, use $math.floori, $math.ceili or $math.roundi.
Vectors
Section titled “Vectors”A position, a direction or a colour is a vector: two, three or four floats together.
| Type | Parts | Used for |
|---|---|---|
vec2 |
x, y |
Screen positions, sizes. |
vec3 |
x, y, z |
World positions, directions, velocities, RGB colours. |
vec4 |
x, y, z, w |
Rotations, and colours with transparency. |
Write a vector of plain numbers as vec3(x, y, z). When any part is computed, build it with the native
$math.vec3 instead:
let up: vec3 = vec3(0, 0, 100)let height: float = 40.0let lifted: vec3 = $math.vec3(0.0, 0.0, height)Read a part with a dot, and add, subtract or scale vectors with the usual operators:
let position: vec3 = vec3(100, 200, 0)let above: vec3 = position + vec3(0, 0, 50)let twice: vec3 = position * 2.0let x: float = above.xIn the game world z points up. Rotations are vec4 quaternions. You rarely build one by hand: natives like
$entity.get_world_rotation hand them to you and $math.eulers_from_rotation turns one into angles.
Engine handles
Section titled “Engine handles”These types don’t hold data themselves. They point at something the engine owns.
| Type | Points at | You get one from |
|---|---|---|
Entity |
An entityentity: A thing in the game world: a player, a ball, a trigger, an empty marker. On its own it only has a name and a place in the hierarchy; components give it behaviour. in the world. | $entity.get(), $entity.get_child_named(…), $component.get_entity(c) |
Component |
A componentcomponent: One script attached to one entity. The same script on ten entities is ten components, each with its own copy of the script's fields.: one script on one entity. | $support.entity_get_component(…), $entity.get_hierarchy_singleton(…) |
User |
A useruser: A person playing, or a bot. Players, the balls they hold and the things they spawn are owned by a user.: a person playing, or a bot. | $entity.get_owning_user_from_entity(e), $user.get_primary() |
Reference |
An asset: a level, a sound event, an effect, a model. | A constant field, set in the level editor. |
Any handle can be null, pointing at nothing. Natives return null when there is no such thing, so check a handle
before you use it. A handle counts as true when it points at something, so ! reads naturally:
let child: Entity = $entity.get_child_named("arrival", true, $entity.get())if !child { return}Lists and var
Section titled “Lists and var”A list holds any number of values in order; Lists and strings covers them.
var means “any type”. You’ll meet it where a native can return different kinds of value, such as reading from a list or
reading another script’s field. Store the result in a variable with the type you expect:
let names: list = ["plaza", "garage"]let first: string = names.get(0)A function parameter written without a type is a var too.
Where you must write the type
Section titled “Where you must write the type”- Fields at the top of a script need a type, unless the starting value is a literal that names it:
let lives = 3is anint,let title = "x"astring,let names = []alist.let target = nulldoes not say which handle it is; writelet target: Entity = null. - Locals inside a function may leave it off; the type comes from the value. Writing it anyway makes the code easier to read, especially for handles.
- Parameters and return types of your functions: write them whenever you know them.
For programmers
Types are checked at compile time where they’re known (natives declare typed parameters, and a mismatch is
V0304), and values carry their type at runtime, which is how var works. Don’t rely on implicit
numeric conversion; convert explicitly with as. Handles are nullable references with truthiness;
there is no Option. There are no user-defined structs: group data in several fields, or in a list.