Cross-Behaviour Calls

In Lemonate, game logic is defined through Behaviour — Lua scripts attached to Scene Objects. Sometimes, one behaviour script needs to call a function defined in another behaviour attached to a different object in the scene graph.

To enable this, Lemonate provides the :behaviour() method on the SceneObject type. This method allows you to access another behaviour scripts by specifying its script item name as a string.

How Cross-Behaviour Calls Work

In Lemonate, Lua does not have type names or reflection features like some other languages. This means you cannot refer to behaviour types directly. Instead, the :behaviour(scriptName) method retrieves the instance of a specific script attached to a node, using the script file name.

Note

The string you pass to :behaviour() must match the item name of the Lua script that defines the behaviour, not the name of the Behaviour that is created inside. This is necessary because Lua does not provide native support for type introspection.

Usage Example

Let’s say you have two scene objects:

  1. A Controller object with a script named MyController

  2. A Box object with a script named BoxController

You want the Controller to call a method on the Box each frame to move it upward.

BoxController

This script defines a method moveBox(translation) on the box behaviour:

local BoxBehaviour = Class.new(Behaviour)

function BoxBehaviour:moveBox(translation)
    self.node:withTransform(function(t)
        t.position.add(translation)
    end)
end

return BoxBehaviour

ControllerBehaviour

This script references the Box behaviour and calls its method during the update loop. Note that it is using the script item’s name “BoxController”, not “BoxBehaviour” which is the behaviour’s name created in the script. In practice, those names should match but it is not guaranteed.

local Vector3 = require 'engine/math/vector3'

local ControllerBehaviour = Class.new(Behaviour)

ControllerBehaviour:addProperty("box", Property.Node)

function ControllerBehaviour:update()
    self.box:behaviour("BoxController"):moveBox(Vector3.new(0, 1, 0))
end

return ControllerBehaviour

Explanation

  • self.box is a node property (set up via the editor or manually).

  • self.box:behaviour("BoxController") returns the behaviour script instance named BoxController attached to the node.

  • :moveBox(...) then calls the method on that script instance.

Best Practices

  • Make sure that the script name passed to :behaviour() matches the item name exactly.

  • Use addProperty(“nodeName”, Property.Node) to link scene objects to each other via the editor.

  • Always check that the target object and behaviour exist before calling methods in more complex scenarios.

Example with Null Check:

function ControllerBehaviour:update()
    if self.box then
        local boxController = self.box:entity("BoxController")
        if boxController then
            boxController:moveBox(0, 1, 0)
        end
    end
end

Summary

  • Use :behaviour(scriptItemName) to call methods on another behaviour script.

  • This enables communication between different objects in the scene graph.

  • Script names (not type names) must be used due to Lua’s limitations.

  • Use this feature when you want modular, decoupled components that interact via explicit links.