Skip to main content

Client scripts

A client script runs on screen, never in the world: it gives a part its colour (VisualEffect) or makes it a light (Light). It saves nothing; its state is always rebuilt from the server's latest values.

/// A light that follows a server field.
client script SignalLight extends VisualEffect
label "Signal light"
category "Server signals"

input lit: bool = false

property onColor: color = #ffd878 "Colour when on" was "color"
property offColor: color = #252a31 "Colour when off"
property strength: float = 1.0 "Strength" range 0 to 1 step 0.05

function apply(baseColor: color, elapsedSeconds: float): color
let target = if lit then onColor else offColor
return baseColor.mix(target, strength).withAlpha(baseColor.a)
end
  • A client script has properties, at most one input and functions. The server's declarations (memory, fields, timers, handlers, states) are refused.
  • input name: type = default binds the script to a server signal: the latest value of a contract field. The binding is set in the editor, on the component's card; its type must match the field's. An input is a value that is read, not an event.
  • An effect starts when its part is ready. It sees its input's latest value, or the default until a value arrives.

VisualEffect​

The entry point is function apply(baseColor: color, elapsedSeconds: float): color.

  • It is called every frame, for every enabled effect of the part, in component order. The first effect gets the material's own colour, the next ones the colour before them; every frame starts again from the own colour.
  • elapsedSeconds is the visual time since the effect started, in seconds: it stops when Play is paused and does not follow the world's speed.
  • The colour an effect gives glows: the part no longer takes the scene's light and shows at night too. An effect that returns the colour unchanged (a neon that is off returning baseColor) leaves the part in the scene's light, as without effects.
  • The script sets the alpha; the examples keep it with withAlpha(baseColor.a).

Light​

Makes the part a light source. The entry point is function apply(elapsedSeconds: float): color: the colour of the light the part casts this frame. Black casts nothing; channels above 1 are brighter; negatives count as 0.

  • Every Light script declares property reach: float: the distance, in metres, at which the light fades out.
  • The light spreads from the part's middle in every direction and fades toward reach; it lights the sides of surfaces that face it.
  • It casts no shadows. The view draws the 8 lights nearest the camera; a hidden part casts no light.

Rules for apply​

  • apply has no side effects and cannot wait: it reads the properties, the input and its parameters, and calls only pure functions (Library).
  • Each call has its own budget.
  • If apply fails (NaN, overflow, budget), that effect is switched off for the session and the chain goes on without it; Play's log shows the error with a link to its line.

Signals​

  • The current value is delivered before the first apply; a client that connects late gets the latest value, not the history.
  • An update of several fields is taken in whole before effects see any of it.
  • Until a value arrives, or when its source is really removed, the input keeps its default; a lost connection does not change the latest value.