Skip to content

2D, text and UI

Sprites, tilemaps, 2D lights and cameras, world text, UI canvases, dialogue and 2D physics.

sprite

A textured quad on the entity's XY plane (2D characters, props, backgrounds, pixel art, 2.5D billboards). Painter's order: sortingLayer, then order, then depth.

Field Type Description Values
texture string Image (png/jpg) or atlas (*.atlas.json), project-relative
frame string Atlas frame name or frame index ("3"); empty = first frame / whole image
columns integer Grid sheet columns (frames left->right, top->bottom)
rows integer Grid sheet rows
region number[] Explicit pixel rect [x, y, w, h] in the image (overrides frame)
pivot number[2] Origin within the frame: [0.5, 0.5] center, [0.5, 0] feet, [0, 0] bottom-left
size number[2] World size [w, h]; 0 = pixels / pixelsPerUnit (one 0 keeps the aspect)
pixelsPerUnit number Texture pixels per world unit (pixel art: 16 or 32) 0.01 .. 100000
color color Tint and opacity — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
flipX boolean Mirror horizontally (face left)
flipY boolean Mirror vertically
sortingLayer string Draw layer (back to front) background midground default foreground overlay
order integer Order within the layer (higher = in front)
filter string Texture sampling: linear (painted art) or nearest (pixel art) linear nearest
normalMap string Normal map for 2D lighting (optional)
emissive color Glow color, alpha = strength (blooms) — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
billboard string Face the camera: none, y (upright, turns around Y) or full none y full
lit boolean Lit by 2D lights when the scene has any (else full bright)
castShadows boolean Blocks shadow-casting 2D lights
alphaCutoff number Hard cutout below this alpha (0 = soft edges) 0 .. 1
visible boolean Whether the sprite is drawn
ySort boolean Top-down depth: among ySort sprites and tile rows of the same layer and order, the one lower on screen (smaller world y at the pivot) draws in front
palette string Palette swap: *.palette.json ({"swap": {"#3a7d44": "#d8e4ec"}}) or a 2-row png (row 0 source colors, row 1 targets); recolors the texture (seasons, variants)
blur number Depth-of-field blur radius in texture pixels: soft out-of-focus foreground silhouettes and far layers (0 = sharp; 4-24 typical) 0 .. 64
sway number[] Wind/cloth sway (the image bends inside its quad): [amplitude as a fraction of the width (0.02-0.1), speed Hz, waves along the height, pin: 0 = bottom fixed (grass, banners on poles), 1 = top fixed (curtains, hanging silk)]; amplitude 0 = off
blend string alpha (normal) or add (light shafts, god rays, glows, sparks: brightens what is behind) alpha add
flash color Hit flash: rgb mixed over the sprite by alpha (0 = none). Wander flash(e, 0.12) plays a fading one — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
entity_update {"entity": "Crate", "components": {"sprite": {}}}
self.sprite.texture          -- read or write any field

sprite_anim

Flipbook animation for the entity's sprite. clips: {"run": {"frames": "4-11", "fps": 12, "loop": true, "events": {"3": "footstep"}}}. frames: index ranges ("0-3,6"), lists ([0, 1, 2] or ["run_0", ...]) or an atlas name pattern ("run_*"); a clip may switch sheets with "texture", "columns", "rows". Frame events reach the entity's behaviors as on anim "footstep"; non-looping clips send on anim "finished".

Field Type Description Values
clips object Clip name ->
clip string Clip playing now (Wander: play_anim(self, "run"))
playing boolean Advance frames
speed number Playback speed multiplier 0 .. 100
entity_update {"entity": "Crate", "components": {"sprite_anim": {}}}
self.sprite_anim.clips          -- read or write any field

sprite_trail

Afterimages behind a moving sprite: dashes, lunges, fast slashes, a swooping boss. While the entity moves faster than minSpeed it records its pose and animation frame every interval seconds; the last count poses are drawn behind the sprite in color, fading out with age. Toggle emitting from Wander around a dash.

Field Type Description Values
emitting boolean Record new afterimages (existing ones still fade out)
count integer Afterimages drawn at most (3-10)
interval number Seconds between afterimages (0.02-0.06) 0.005 .. 2
minSpeed number World units per second needed to record (0 = always) 0 .. 1000
color color Tint of the afterimages — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
opacity number Opacity of the newest afterimage 0 .. 1
emissive number Glow of the afterimages (blooms in HDR) 0 .. 50
additive boolean Blend additively (energy streaks) instead of as translucent copies
entity_update {"entity": "Crate", "components": {"sprite_trail": {}}}
self.sprite_trail.emitting          -- read or write any field

tilemap

A grid of tiles in layers. Cell (0, 0) is the top-left at the entity position; cells go right (+x) and down (-y) in world space. Tile ids: 0 = empty, n = the n-th tile of the tileset (1-based, left->right, top->bottom). Edit with tilemap_paint / tilemap_from_ascii; layer data is compact text ("rle:..." or "b64z:...").

Field Type Description Values
tileset string Tileset image (grid of tiles) or *.tileset.json
tileSize integer Tile size in tileset pixels
cellSize number World units per cell 0.001 .. 1000
width integer Columns
height integer Rows
layers object[] [{name, data, solid (true | "tiles"), visible, z, tint, sortingLayer, order, ySort}] bottom to top; a ySort layer draws row by row, interleaved with ySort sprites (tall tiles: the tileset's sortOffset)
solidTiles array Tile ids that collide in layers with solid: "tiles" ([3, "10-20"])
autotile object Terrains for auto-tiling: {"wall": {"mode": "blob47" | "wang16", "first": 33}} or "tiles": [ids]
color color Tint — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
sortingLayer string Draw layer of all tile layers (unless a layer overrides it) background midground default foreground overlay
order integer Order within the sorting layer (each tile layer adds its index)
filter string Texture sampling nearest linear
lit boolean Lit by 2D lights
castShadows boolean Solid tiles block shadow-casting 2D lights
palette string Palette swap for the tileset image (*.palette.json or a 2-row png strip)
entity_update {"entity": "Crate", "components": {"tilemap": {}}}
self.tilemap.tileset          -- read or write any field

light2d

A 2D light: point, spot (cone along the entity's local +Y) or global (ambient for the whole 2D scene). With any 2D light in the scene, lit sprites are dark except where light falls; normal maps add relief.

Field Type Description Values
kind string point | spot | global (ambient) point spot global
color color Light color — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
intensity number Brightness (HDR: > 1 blooms) 0 .. 1000
radius number Reach in world units 0.01 .. 100000
falloff number Attenuation exponent: 1 linear, 2 soft, 4 tight 0.1 .. 16
innerAngle number Spot: full-intensity half-angle (degrees) 0 .. 180
outerAngle number Spot: cutoff half-angle (degrees) 0 .. 180
height number Height above the sprite plane (normal-map relief) 0 .. 100
shadows boolean Cast shadows from castShadows sprites and solid tiles
shadowSoftness number Penumbra softness 0 .. 1
halo number Visible glow in the air around the light 0 .. 10
flicker number Candle/torch flicker amount 0 .. 1
bands integer Pixel-art falloff: 0 = smooth gradient; n = n stepped rings joined by an ordered dither on the art's texel grid (no 8-bit banding; 4-8 suits pixel art)
entity_update {"entity": "Crate", "components": {"light2d": {}}}
self.light2d.kind          -- read or write any field

particles2d

Pixel-art particles on the 2D plane: rain streaks, snow, falling leaves and petals, fireflies, chimney puffs, puddle ripples. Drawn as sprites (nearest sampling, texel snapping, sorting layers) from a sheet or as solid pixel rectangles; simulated deterministically on fixed ticks. wrap = true tiles the emission box endlessly so weather fills whatever the camera shows. Create tuned ones with particles2d_create.

Field Type Description Values
emitting boolean Spawn new particles (live ones finish their life)
texture string Grid sheet (png) or atlas; empty = solid rectangles of pixelSize texels
columns integer Sheet columns
rows integer Sheet rows
frames string Frames to use ("0-3,6"; empty = all)
animate string random: each particle keeps one frame; life: frames play over its life; loop: at fps random life loop
fps number Frames per second (animate = loop) 0 .. 120
pixelsPerUnit number Texels per world unit (match the art, e.g. 16) 0.01 .. 100000
pixelSize number[2] Untextured particles: [w, h] in texels (rain streak: [1, 4])
rate number Particles per second 0 .. 100000
burst integer Particles emitted at once when play starts
maxParticles integer Cap on live particles
lifetime number Seconds a particle lives 0.01 .. 600
lifetimeJitter number Random fraction of the lifetime 0 .. 1
area number[2] Emission box [w, h] in world units, centered on the entity
wrap boolean Tile the box endlessly around the view (weather that fills any camera)
velocity number[2] Initial velocity (world units/s)
velocityJitter number[2] Random +- added per axis
gravity number[2] Acceleration (world units/s^2); [0.3, 0] works as wind
drag number Velocity damping per second 0 .. 100
sway number Side-to-side drift speed (leaves, snow) 0 .. 100
swayFrequency number Sway cycles per second 0 .. 50
flutter number Random-walk wander (fireflies, butterflies) 0 .. 100
color color Tint and opacity — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
colorJitter number Per-particle brightness variation 0 .. 1
emissive color Glow color, alpha = strength (blooms) — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
pulse number Twinkle depth of opacity and glow (fireflies) 0 .. 1
pulseFrequency number Twinkles per second 0 .. 50
fadeIn number Fraction of the life spent fading in 0 .. 1
fadeOut number Fraction of the life spent fading out 0 .. 1
sortingLayer string Draw layer background midground default foreground overlay
order integer Order within the layer
lit boolean Lit by 2D lights (else full bright)
prewarm boolean Start as if it had been running for a while
seed integer Random seed (same seed, same particles)
filter string nearest (pixel art, texel-snapped) or linear (painted motes, smooth sub-pixel motion) nearest linear
blend string alpha (normal) or add (sparks, embers, glowing spores) alpha add
sizeJitter number Random size per particle: 0.5 = 50% to 150% 0 .. 1
entity_update {"entity": "Crate", "components": {"particles2d": {}}}
self.particles2d.emitting          -- read or write any field

parallax

Parallax scrolling for this entity and its children (2D, orthographic cameras): they move at factor of the camera's motion. 0 = fixed to the camera (sky), 0.1-0.6 = far layers, 1 = normal, > 1 = near foreground.

Field Type Description Values
factor number[2] Motion relative to the camera per axis
origin number[2] Camera position at which the layer is at its authored position
repeatX boolean Repeat sprites horizontally to fill the view (endless backgrounds)
repeatY boolean Repeat sprites vertically
spacing number Repeat period in world units (0 = sprite size) 0 .. 1000000
entity_update {"entity": "Crate", "components": {"parallax": {}}}
self.parallax.factor          -- read or write any field

camera2d

2D camera behavior (put it on the camera entity): orthographic, pixel-perfect integer scaling, texel snapping, smooth target following with a dead zone, and level bounds.

Field Type Description Values
pixelsPerUnit number Art texels per world unit (match the sprites) 0.01 .. 100000
referenceHeight integer Game pixels tall (e.g. 180 or 270): integer upscaling for crisp pixel art; 0 = camera.orthoSize
pixelSnap boolean Snap the view to the texel grid (no shimmering)
zoom number Zoom factor (> 1 = closer) 0.01 .. 100
follow object | string | integer | null Entity to follow; empty = none — entity link: name ("Door"), "#id", {"id": 12} or null; read back as {"id", "name"} (follows renames; entity_refs lists links)
smoothing number Follow lag in seconds (0 = rigid) 0 .. 10
deadZone number[2] Half-size of the box the target moves in without moving the camera
offset number[2] Framing offset from the target
bounds number[] [minX, minY, maxX, maxY] the view stays inside (all 0 = unbounded)
shakeAmplitude number camera_shake: world units of offset at full trauma 0 .. 100
shakeFrequency number camera_shake: noise frequency (Hz) 0.1 .. 120
shakeDecay number camera_shake: trauma lost per second 0 .. 100
entity_update {"entity": "Crate", "components": {"camera2d": {}}}
self.camera2d.pixelsPerUnit          -- read or write any field

text

Text in the world (signs, labels, damage numbers, speech bubbles). SDF-rendered: crisp at any zoom. Supports rich text:
.

Field Type Description Values
text string The text (rich text tags allowed)
font string Inter (default), EB Garamond (serif), JetBrains Mono (mono), or a .ttf path
size number Em size in world units 0.001 .. 10000
color color Text color — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
align string Horizontal alignment around the entity left center right justify
valign string Vertical alignment around the entity top middle bottom
maxWidth number Wrap width in world units (0 = no wrap) 0 .. 1000000
lineSpacing number Line height multiplier 0.1 .. 10
outline number Outline width in em 0 .. 0.15
outlineColor color Outline color — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
shadowColor color Drop shadow color (alpha 0 = none) — hex string "#rrggbb[aa]" or [r,g,b(,a)] in 0..1
shadowOffset number[2] Drop shadow offset in world units
emissive number Glow strength (neon signs bloom) 0 .. 100
billboard string Face the camera none y full
sortingLayer string Draw layer background midground default foreground overlay
order integer Order within the layer
visible boolean Whether the text is drawn
entity_update {"entity": "Crate", "components": {"text": {}}}
self.text.text          -- read or write any field

ui_canvas

Root of a user interface. Children with a ui component are laid out in canvas pixels (origin top-left, y down). screen = overlay scaled from referenceResolution; world = a panel in the scene. Build whole UIs with ui_create; restyle with ui_style.

Field Type Description Values
mode string screen overlay or world-space panel screen world
referenceResolution number[2] Design resolution [w, h] in pixels
scaleMode string scale_with_screen (resolution independent) or constant (1 px = 1 px) scale_with_screen constant
match number Scaling: 0 = match width, 1 = match height 0 .. 1
sortOrder integer Canvases draw in ascending order
theme string Built-in look dark light parchment glass pixel
styleSheet string Style sheet (*.uistyle.json) layered over the theme
worldScale number World mode: world units per canvas pixel 1e-05 .. 100
interactable boolean Receives mouse/keyboard input
entity_update {"entity": "Crate", "components": {"ui_canvas": {}}}
self.ui_canvas.mode          -- read or write any field

ui

A UI element under a ui_canvas. Rect: anchor preset + position (offset, y down) + size, or stretch with margin. A layout (row/column/grid) arranges children with gap/padding/align/justify; fit sizes to content. Look comes from the theme/style sheet by widget kind and style classes, plus styleOverrides. Activating a button/toggle/slider sends Wander on ui "<name>" (and on click to the element).

Field Type Description Values
widget string What it is panel image text button toggle slider progress scroll input spacer
anchor string Where it attaches in its parent: corners/edges/center, fill, or *_stretch bands; custom uses anchorMin/anchorMax/pivot top_left top top_right left center right bottom_left bottom bottom_right fill top_stretch middle_stretch bottom_stretch left_stretch center_stretch right_stretch custom
anchorMin number[2] custom anchor: parent fraction [x, y] (0,0 = top-left)
anchorMax number[2] custom anchor: parent fraction [x, y]; differs from anchorMin = stretch
pivot number[2] custom anchor: the element's own reference point [x, y] (0,0 = top-left)
position number[2] Offset from the anchor in pixels [x, y] (y down)
size number[2] Size in pixels [w, h] (ignored on stretched axes)
margin number[] Insets on stretched axes [top, right, bottom, left]
layout string Arrange children none row column grid
gap number Space between children (pixels) 0 .. 100000
padding number[] Inner padding [top, right, bottom, left] (CSS shorthand ok: 12 or [8, 16])
align string Children on the cross axis start center end stretch
justify string Children on the main axis start center end space_between
columns integer Grid columns
fit string Size to content (children or text) none width height both
flex number Share of leftover space in a row/column (0 = fixed size) 0 .. 1000
ignoreLayout boolean Placed by its own anchor even inside a layout
text string Label or content (rich text)
image string Image path or atlas frame ("ui.atlas.json#heart")
value number Slider/progress value; toggle: 0 or 1
minValue number Slider/progress minimum
maxValue number Slider/progress maximum
placeholder string Input: hint shown when empty
style string Style classes, space separated ("primary large")
styleOverrides object Inline style properties ({"background": "#223", "radius": 12})
event string Extra event sent when activated (in addition to ui:<name>)
interactable boolean Receives input (disabled look when false)
visible boolean Shown (hidden elements and their children take no space)
scroll number Scroll views: content offset in pixels
entity_update {"entity": "Crate", "components": {"ui": {}}}
self.ui.widget          -- read or write any field

dialogue

Runs a .dialogue script (Yarn-style: nodes, Speaker: line #tags, -> choices, <>, <>, <>, custom <> sent to Wander as on dialogue "name") with a built-in, restylable dialogue box. Start it with Wander start_dialogue("Node"); lint with dialogue_check; simulate with dialogue_preview.

Field Type Description Values
script string Dialogue file (*.dialogue), project-relative
source string Inline script (used when script is empty)
startNode string Node to start at
autoStart boolean Start when play begins
ui string default = built-in dialogue box; none = drive your own UI default none
typewriter number Characters per second (0 = instant) 0 .. 10000
portraits string Folder for #portrait:<name> tags (<name>.png)
running boolean State: a conversation is in progress
node string State: current node
speaker string State: speaker of the current line
line string State: current line text
choices string[] State: current choices (array of strings)
tags object State: tags of the current line ({"mood": "angry"})
entity_update {"entity": "Crate", "components": {"dialogue": {}}}
self.dialogue.script          -- read or write any field

body2d

Simulated 2D rigid body (Box2D) on the XY plane: dynamic = moved by gravity, forces and collisions; kinematic = moved by its transform or velocity (moving platforms, doors) and pushes dynamic bodies; static = never moves. Shape it with a collider2d on the entity or its children. It writes position x/y and the Z rotation.

Field Type Description Values
motion string How the body moves dynamic kinematic static
mass number Mass in kg (0 = from the colliders' density x area) 0 .. 10000000
gravityScale number Gravity multiplier (0 = floats, -1 = falls up) -100 .. 100
linearDamping number Drag on movement 0 .. 100
angularDamping number Drag on spinning 0 .. 100
fixedRotation boolean Never rotates (upright crates, force-driven characters)
bullet boolean Continuous collision against other moving bodies: fast projectiles never tunnel
allowSleep boolean May sleep when at rest (saves time; woken by contacts)
startAwake boolean Simulate from the start (false = sleep until touched)
velocity number[2] Linear velocity in units/s (initial; live while playing, writable)
angularVelocity number Angular velocity in degrees/s around Z (initial; live while playing)
sleeping boolean Whether the body sleeps (live while playing, read-only)
entity_update {"entity": "Crate", "components": {"body2d": {}}}
self.body2d.motion          -- read or write any field

collider2d

2D collision shape on the XY plane. Alone it is static geometry (ground, walls); with a body2d it shapes the body; on a child without its own body2d it adds a shape to the ancestor's body. sensor makes a zone that fires on trigger_enter / on trigger_exit. oneWay makes a platform you can jump through from below. shape tilemap builds merged collision from the entity's tilemap (solid layers, per-tile slopes and one-way tiles).

Field Type Description Values
shape string Shape type box circle capsule polygon chain segment tilemap
size number[2] Box: full width and height (local units, scaled by the transform)
radius number Circle/capsule radius (local units) 0 .. 100000
height number Capsule total height along local Y (>= 2 x radius) 0.001 .. 100000
offset number[2] Shape center relative to the entity origin (local)
rotation number Shape rotation around Z relative to the entity (degrees)
points number[2][] Polygon (convex, 3..8 points), chain (>= 4 points) or segment (2 points), local: [[x, y], ...]
loop boolean Chain: closed loop (counter-clockwise collides on the outside)
friction number Surface friction (ice 0.02, wood 0.6, rubber 1) 0 .. 10
restitution number Bounciness: 0 = none, 1 = perfectly elastic 0 .. 1
density number kg per square unit (gives dynamic bodies their mass) 0 .. 1000000
sensor boolean Sensor: detects overlaps (trigger_enter/exit) but never blocks
layer string Collision layer default static player enemy projectile trigger debris
mask string Layers it collides with: "all" or names ("default, player")
oneWay boolean One-way platform: blocks only from above (local +Y), passable from below
tileMerge string Tilemap: chains = merged outlines (smooth), boxes = merged rectangles chains boxes
tileShapes object Tilemap: per-tile shapes over the tileset's collision table, by tile id: full | none | slope_up | slope_down | half_bottom | half_top | top (one-way), or {"points": [[px, py], ...], "oneWay": true} in tile pixels (origin top-left, y down)
entity_update {"entity": "Crate", "components": {"collider2d": {}}}
self.collider2d.shape          -- read or write any field

character2d

Kinematic platformer controller on the XY plane: a capsule that slides along walls, walks up and down slopes up to maxSlope, lands on one-way platforms, with its own gravity, coyote time and jump buffering. Drive it every tick from Wander: move2d(self, axis("move").x), if pressed("jump") then jump2d(self) end, grounded2d(self). Dynamic bodies are pushed by it; sensors detect it.

Field Type Description Values
height number Capsule height (units) 0.05 .. 100
radius number Capsule radius (units) 0.02 .. 50
offset number[2] Capsule center relative to the entity origin (y = height/2: origin at the feet)
moveSpeed number Run speed in units/s at move2d(self, 1) 0 .. 1000
acceleration number Ground acceleration in units/s^2 0 .. 10000
airControl number Share of the acceleration in the air (0..1) 0 .. 1
jumpSpeed number Jump take-off speed in units/s 0 .. 1000
gravity number Downward acceleration in units/s^2 0 .. 10000
fallMultiplier number Gravity multiplier while falling (snappier jumps) 1 .. 10
maxFallSpeed number Terminal fall speed in units/s 0 .. 1000
maxSlope number Steepest walkable slope in degrees 0 .. 89
coyoteTime number Seconds after leaving a ledge in which a jump still works 0 .. 2
jumpBuffer number Seconds a jump pressed in the air is remembered until landing 0 .. 2
snapDistance number Stays glued to the ground across slopes and small steps (units) 0 .. 10
layer string Collision layer default static player enemy projectile trigger debris
mask string Layers it collides with: "all" or names
velocity number[2] Velocity in units/s (live while playing; writable: knockback, launch pads)
grounded boolean Standing on walkable ground (live while playing, read-only)
entity_update {"entity": "Crate", "components": {"character2d": {}}}
self.character2d.height          -- read or write any field

joint2d

Connects this entity's 2D body to another body (other) or to the world. revolute = hinge/pivot (wheels, doors, ragdoll limbs), prismatic = slider, distance = rod or spring, weld = glue (breakable with breakForce), wheel = car wheel with suspension along axis, target = pulls the body to a world point or the other entity (drag, grapple).

Field Type Description Values
kind string Joint type revolute prismatic distance weld wheel target
other object | string | integer | null The other body (empty = the world; target: the entity to follow) — entity link: name ("Door"), "#id", {"id": 12} or null; read back as {"id", "name"} (follows renames; entity_refs lists links)
anchor number[2] Pivot in this entity's local space
otherAnchor number[2] The other end in the other body's local space (world point without other)
axis number[2] Prismatic/wheel axis in this entity's local space
length number Distance: rest length (0 = the distance at play start) 0 .. 100000
limitMin number Lower limit: degrees (revolute) or units; active when min < max
limitMax number Upper limit
motorSpeed number Motor speed: degrees/s (revolute, wheel) or units/s (prismatic)
motorForce number Max motor torque (N m) or force (N); 0 = motor off 0 .. 1000000000
stiffness number Spring frequency in Hz (0 = rigid) 0 .. 1000
damping number Spring damping ratio (0.7 = settles without bouncing) 0 .. 100
target number[2] Target joint: world point to pull to (when other is empty)
maxForce number Target joint: strongest pull in N 0 .. 1000000000
breakForce number Breaks above this force in N (0 = unbreakable) 0 .. 1000000000
collideConnected boolean The two bodies collide with each other
enabled boolean false after breaking (on event "joint_broken")
entity_update {"entity": "Crate", "components": {"joint2d": {}}}
self.joint2d.kind          -- read or write any field

physics2d_world

Scene-wide 2D physics settings (put it on one entity; defaults apply without one): gravity, solver sub-steps, sleeping, the impact event threshold and debug drawing of shapes, contacts and joints.

Field Type Description Values
gravity number[2] Gravity in units/s^2 (default 0, -20)
substeps integer Solver sub-steps per tick (1..16; more = stiffer stacks)
allowSleep boolean Bodies at rest may sleep
impactSpeed number Approach speed (units/s) above which on impact fires 0 .. 10000
debugDraw boolean Draw shapes, contacts and joints in the frame
enabled boolean Simulate 2D physics
entity_update {"entity": "Crate", "components": {"physics2d_world": {}}}
self.physics2d_world.gravity          -- read or write any field