Skip to content

objects

Acting on other objects — the ones you did not spawn and are not standing in.

luau
local objects = require("objects")

objects also works without the require, as a ready-made global.

Finding one

me

objects:me() → object, or nil

This script's own object, as an ordinary reference. This is how a script reads or changes its own tags.

nil on a personal HUD and on a worn item: neither is an object in the world.

get

objects:get(id) → object, or nil

One object by its id. Only persistent objects — things world:spawn made are not in here.

tagged

objects:tagged(tag) → list, or nil, reason

Every object carrying that tag.

luau
local lamps = objects:tagged("streetlight")
if lamps then
    for _, lamp in ipairs(lamps) do
        lamp:set({ light = true })
    end
end

Refused with a reason when more than 256 objects match — a query that broad is almost always a mistake, and answering it would stall the region.

named

objects:named(name) → list, or nil, reason

Exact display-name lookup, ignoring capitals. Names are not unique, so this always answers a list.

Prefer tags to names. A name is what a person reads and may rename on a whim; a tag is what a script means. Tagging every lamp "streetlight" survives somebody renaming one to "Lamp (broken)".


What you get back

Each result carries four readings:

FieldMeaning
idits permanent id in this region
nameits display name, or nil once it has been removed
ownerthe id of whoever owns it, or nil if unstamped
tagsits tags, sorted — a snapshot, not a live view
luau
obj:exists()            -- is it still in the world?
obj:has_tag("door")     -- ignoring capitals

Moving it

VerbMeaning
obj:move_to(x, y, z)put it there
obj:rotate_to(x, y, z)face that way, degrees
obj:scale_to(n)resize. One number is uniform, three are per axis
obj:move_by(x, y, z)move by a step, from wherever it actually is
obj:rotate_by(x, y, z)turn by an angle, about its own axes

All answer true, or nil plus a reason. Coordinates are local to the parent when the object is inside a group and world coordinates when it stands alone — the same rule as everywhere else.

Requires that you own the object, or have been granted edit rights over it.

You cannot read another object's position, and this is deliberate. Doing so would mean mirroring the whole region's motion into every script on every tick, which is a cost every script would pay for a question few of them ask.

Say "a bit more" instead. move_by and rotate_by are added to the object's live transform at the moment they are applied — which is also the only version that survives somebody else moving the object in between.


Changing it

set

obj:set(changes)true, or nil, reason

The same property table self:set takes.

luau
lamp:set({ light = true, emissive = 2, color = "#ffe9b0" })

tween

obj:tween(opts)true, or nil, reason

A smooth change, run by the region. Same options as self:tween.

No handle comes back — use self:after(seconds, ...) when something must happen on arrival.

add_tag / remove_tag

obj:add_tag(tag)true, or nil, reasonobj:remove_tag(tag)true, or nil, reason

One tag at a time, applied atomically. Up to 16 tags per object. Removing a tag that is not there is harmless.

Tags are how objects talk about each other without reading each other. A script cannot ask another object for its state — but it can ask whether it carries a tag, and the object's own script controls its tags. That makes a tag the public half of an object: "door.open" says something true that anyone may check.

damage / heal

obj:damage(amount, { by = uuid })true, or nil, reasonobj:heal(amount)true, or nil, reason

Hurts or mends a damageable object — one with a max_health.

Unlike self:damage, these answer true, not the remaining health. No script holds a mirror of another object's life. For the outcome, listen for world.destroyed.

remove

obj:remove()true, or nil, reason

Takes it out of the world, cascading through its group.

It goes to the world's trash, where it can be restored with its scripts and its memory intact. It is not an erasure.


A worked example

Every lamp in the world comes on at dusk and goes off at dawn, driven by one object:

luau
--!strict
local self = require("self")
local objects = require("objects")
local world = require("world")

local DAY = 600      -- a full cycle, in seconds

local lit = false

local function set_all(on: boolean)
    local lamps = objects:tagged("streetlight")
    if not lamps then
        print("too many lamps to address at once")
        return
    end

    for _, lamp in ipairs(lamps) do
        lamp:set({
            light = on,
            emissive = on and 2.5 or 0,
        })
    end
end

self:on_timer(10, function()
    local phase = world:clock() % DAY
    local should = phase > DAY * 0.5

    if should ~= lit then
        lit = should
        set_all(lit)
    end
end)

Two things worth stealing:

  • It only acts when the answer changes, not every ten seconds. Writing the same properties over and over would spend the region's budget for nothing.
  • The lamps are found by tag, so adding a lamp to the world is a build action, not a code change.

See also

Hungrit scripting documentation.