Voxel Game Maker

Docs Quick code

Objects

self, player, object() and objects(); moving, turning, easing, following; their fields and their own values.

#Getting hold of one

Code What it is
self The object this script is on (nil in a level script).
player The player character.
object("front_door") The object with that Script name in this level (Properties ▸ Object ▸ Script name; capitals don't matter).
objects("enemy") A list of every object whose model has that tag.
other What this object just bumped into, or the player after a touched event; nil otherwise.
nearest("enemy"), objects_near(self, 5) See Finding things.
spawn("Goblin", x, level, z) A new copy of a prefab or model — it gives the new object.

Call commands with a dot or a colon — self.move(…) and self:move(…) are the same. An object that isn't there (removed, or object() found nothing) doesn't crash the code: commands on it do nothing, obj.exists is false, and the Output panel says so once.

#Moving and turning

Command Does
move(dx, dy, dz, seconds = 1, wait = true, ease = "smooth") Glide by an offset: dx / dz in tiles, dy in height levels.
move_to(x, y, z, seconds = 1, wait = true) Glide to a tile (x, level, z).
go_home(seconds = 1, wait = true) Glide back to where it was placed.
teleport(x, y, z) or teleport(vec) Jump there at once. Works on player too.
turn(degrees, seconds = 0.5, wait = true) Turn round its middle; + is to the left.
face(degrees, seconds = 0.3, wait = true) Turn to a direction (0 faces -Z, 90 faces -X).
look_at(target, seconds = 0.3, wait = true) Turn to face an object, the player or a position.
tween(what, to, seconds = 1, ease = "smooth", wait = true) Glide one of "x", "y", "z", "position", "turn" or "scale" to a value.
set_scale(size, seconds = 0) Grow or shrink it (1 = normal).
follow(target, speed = 3, keep = 1.5) Keep walking after something, stopping keep tiles away.
flee(target, speed = 3) Keep walking away from it.
stop() Stop following / fleeing / gliding.

Gliding commands wait until they arrive, unless you pass wait = false — then the code carries on while it moves. seconds = 0 jumps there at once.

Easing — how a glide speeds up and slows down: "smooth" (the usual), "linear", "in", "out", "bounce", "elastic", "back".

self.tween("y", self.y + 2, 0.6, "back")     -- pops up with a little overshoot
self.move(0, -2, 0, 0.8, true, "bounce")     -- drops and bounces
self.set_scale(1.5, 0.3)                      -- grows over 0.3 s

Followers walk straight at their target and stop at anything solid (they don't walk through things); for a real route use path_to. Objects with Patrol or Chase behaviors move themselves — leave those to their behaviors.

#Looks and sounds

Command Does
hide() / show() Invisible and walk-through / back again.
remove() Gone for the rest of the game.
tint(color) Colour it: "red", "gold", "#ff8800"; tint("") gives its own colours back.
say(text, seconds = 2.5) A speech bubble over it.
play(animation, keep = false) One of its part animations (Model tab ▸ Timeline).
particles(effect, size = 1) A particle effect on it.
attach(model, point = "Right hand") / detach(point) Show a model on one of its attachment points.
show_hud() / hide_hud() Its Attached HUD (nameplate, health bar…).

#Health

obj.hp and obj.max_hp read an object's health (objects with the Health behavior, and player). obj.hurt(n) and obj.heal(n) change it — hurting an object with Health shows the hit and can defeat it, like an attack. An object without Health can still have its own hp value (below): hurt takes from that, and obj.hp = 5 sets it.

#Asking about it

Field / command Value
x, y, z Where it is, in tiles / levels (fractions mid-glide). Setting one moves it there.
position The same as a vector; set it to move it: self.position = vec(4, 0, 9).
name Its Script name.
exists false if it was removed, or object() found nothing.
model, tags Its model's name, and its model's tags (a list).
hidden true while hidden (set it to hide or show it).
turn Which way it faces, in degrees (set it to turn it at once).
distance(other) Tiles between this and other (an object or player).
touching(what) true if it's touching what: an object, player, or a tag ("enemy", "any").
can_move(dx, dy, dz) true if that move wouldn't run into anything solid.
has_tag(tag) true if its model has that tag.

#Their own values

Any object (and the player) can hold its own values — health of a crate, whether a chest was opened, who a villager is angry with:

self.opened = true
self.hits = (self.hits or 0) + 1
object("gate").locked_by = "Mira"
player.coins_found = 3

They last while the game runs and are saved with the game. Each level keeps its objects' values for when the player comes back; the player's own values go with the player.

Starting values can be typed in the editor: select the object, Properties ▸ Values for code, one per line:

hp = 10
loot = ["Coin", "Gem"]
angry = false

Code reads them as self.hp (in the object's own script) or object("name").hp, and can change them. (The names of the built-in fields above — x, name, model… — are taken.)

#Bumping and touching

Objects don't push each other (gliding objects pass through things), but scripts can notice when they meet, and check before moving:

-- React when something bumps into it: in code…
on("bumped", function(what)
  if what.name == "goal" then win() end
end)

-- …or with an Event node "It bumps into something" (Bumps into: player / any / tags);
-- there, `other` is what it bumped into.

-- Check before you move: step along X until something is in the way.
for i = 1, 10 do
  if not self.can_move(1, 0, 0) then break end
  self.move(1, 0, 0, 0.25)
end
  • Boxes count as touching when they meet or overlap; ground tiles never count.
  • Removed and hidden objects don't count.
  • can_move only cares about solid objects (not Walk-through or pickups) and the player.