Skip to content

Node Game Events

Scene objects can emit game events that scripts listen to with node:on / node:once. These are per-node gameplay signals (agent arrived, player jumped, …). They are separate from the global Events module (pointer, keyboard, physics, …).

Global Events.on node:on / node:once
Engine-wide input / bus One scene object instance
Events.on('pointerdown', …) self.node:on("goalReached", …)

Listening

Register in init (or whenever you hold a node reference). Callbacks receive an event table with type and optional data:

local MyBehaviour = Class.new(Behaviour)

function MyBehaviour:init()
    self.node:on("goalReached", function(ev)
        print(ev.type)           -- "goalReached"
        print(ev.data.goalType)  -- e.g. "GoTo"
    end)

    -- Fire once, then unsubscribe automatically
    self.node:once("landed", function(ev)
        print("first landing")
    end)
end

return MyBehaviour

You can listen on any node you have a handle to (not only self.node):

function MyBehaviour:init()
    local agent = self.node:findByName("Guard")
    if agent then
        agent:on("waypointReached", function(ev)
            print("guard waypoint", ev.data.index)
        end)
    end
end

Stop listening with node:off(eventType) (removes listeners for that type from the current script on that node). Listeners are also cleaned up when the behaviour is destroyed.

Emitting custom events

Scripts may emit events only on the node they are attached to:

function Door:open()
    self.open = true
    self.node:emit("opened", { by = "player" })
end

Other behaviours listening on that node receive { type = "opened", data = { by = "player" } }.

Built-in events

SgAgent

Emitted by Crowd agents. See SgAgent and Navigation and AI.

Event When
goalReached GoTo arrived, or Patrol finished without loop
waypointReached Patrol hit a waypoint, or Wander picked a point

goalReached payload:

data Description
goalType "GoTo" or "Patrol"

waypointReached payload:

data Description
index Patrol waypoint index (Patrol only)
goalType "Wander" when wandering
local SgAgent = require 'engine/sceneobjects/sgagent'
local Vector3 = require 'engine/math/vector3'

function Guard:init()
    self.node:on("goalReached", function(ev)
        if ev.data.goalType == "GoTo" then
            self.node:setGoal(SgAgent.GoalType.Idle)
        end
    end)

    self.node:on("waypointReached", function(ev)
        print("waypoint", ev.data.index or ev.data.goalType)
    end)

    self.node:setGoal(SgAgent.GoalType.GoTo, {
        point = Vector3.new(10, 0, 0),
    })
end

SgPlayer

Emitted by the kinematic player controller. See SgPlayer.

Event When
jump Jump started while grounded
landed Became grounded after being airborne
startWalking Horizontal move state → walking
endWalking Left walking state
startRunning Horizontal move state → running (sprint)
endRunning Left running state

These events currently have no data payload (ev.data is nil).

function PlayerFx:init()
    self.node:on("jump", function()
        -- play jump sound / animation cue
    end)
    self.node:on("landed", function()
        -- play land FX
    end)
end

Variable sets (per-node)

When a node-scoped Variable Set value changes, the node also emits variableChanged (in addition to the global Events bus). Payload:

data Description
set Variable set name
name Variable name
value New value

See Variable Sets and the global variableChanged section in Events.

API summary

Method Role
node:on(type, fn) Listen until off or behaviour destroy
node:once(type, fn) Listen for the next matching event only
node:off(type) Remove this script's listeners for type
node:emit(type, data?) Emit from a script on this node only