Skip to content
Berke edited this page Oct 10, 2026 · 5 revisions

Sprite

Inspector name: Sprite · Lua: entity.sprite · Public field type: Sprite

A Sprite draws a flat image in the world at the entity's position: the classic way to show monsters, items, lamps and decorations in a sector-based game. It can always turn to face the camera, and it can swap between 4 or 8 pictures depending on which side you look at it from, so a monster looks different from the front, the side and the back.

How it works

Size and position

The image stands upright with its bottom centre on the entity's Transform position, which is the feet:

  • width = the Transform's scale.x
  • height = the Transform's scale.z

The Transform's scale.y isn't used by sprites. New entities start at scale 32, a 32 × 32 sprite.

Several on one entity

An entity can have several Sprites, all drawn. Each sits at the Transform position plus its offset (turned with the entity's rotation). They all use the Transform's scale. entity.sprite is the first one; entity:GetComponents(Component.Sprite) lists them all. See Several components of one type.

Facing the camera

  • Normal sprites (Is Static off) are billboards: they always turn to face the camera around the vertical axis, and always stay upright. You can never see them edge-on.
  • Static sprites (Is Static on) don't turn. They're oriented by the Transform's rotation, like a flat card or poster placed in the world. Viewed side-on they're a thin line.

Is Active

An inactive sprite isn't drawn at all, in the game or in the editor's 3D view. Everything else about the entity carries on: its scripts run, its Collider still collides and its Audio Source still plays. Use it to hide something and show it again later without removing the component.

Directions

Direction Level chooses how many pictures the sprite has:

Direction Level Lua sideCount Pictures used
Single 0 Only the first (North) picture, from every angle.
8-Sided 1 All eight: N, NE, E, SE, S, SW, W, NW.
4-Sided 2 Four: N, E, S, W.

With 4 or 8 sides, the engine compares the sprite's facing with the direction from the sprite to the camera. The facing is the way the Transform's rotation points (its local +Z), flattened onto the map, so only rotation Y matters. Rotation 0, 0, 0 faces +Z.

  • N (North) is shown when the camera is in front of the sprite, looking at its face.
  • S (South) is shown when the camera is behind it.
  • The others follow in order around the sprite: N, NE, E, SE, S, SW, W, NW. Each picture covers a 45° slice with 8 sides, or a 90° slice with 4.

To turn a directional sprite, set its rotation: Rotation Y in the inspector, or transform:LookAt(point) / transform:LookDirection(direction) from Lua. If the side pictures appear on the opposite sides from what you expected, swap E with W (and NE with NW, SE with SW).

Colour and light

  • Color tints the image. Each channel 0..1 multiplies the texture's colour.
  • The alpha of Color does not make the sprite transparent. Only the texture's own transparency counts: pixels with alpha below 0.1 are cut out completely, everything else is fully opaque. There is no partial transparency.
  • The sector's light darkens the sprite. Each channel of the tint is reduced by (255 - light) / 255, so a sector light of 128 takes about half off.
  • A picture slot with no texture draws as a solid black rectangle. Fill every slot the Direction Level uses.

In the editor

Field Lua Default Notes
Texture Index (one per direction) northTextureFileName, ... or GetTextureFileName(slot) empty Image paths relative to Assets.
Direction Level sideCount Single See Directions.
Color color 1, 1, 1, 1 Tint.
Is Static off Editor only.
Is Active isActive on Off = not drawn. See Is Active.
Offset offset 0, 0, 0 See Several on one entity.

Scripting

Property Type Description
isValid boolean read-only false if the entity or its Sprite is gone.
isActive boolean read/write false hides the sprite.
offset Vector3 read/write Position relative to the Transform, turned with its rotation. See Several on one entity.
color Vector4 read/write Tint, 0..1.
sideCount integer read/write 0 single, 1 8-sided, 2 4-sided. Other values are ignored.
northTextureFileName string read/write Slot 0.
northEastTextureFileName string read/write Slot 1.
eastTextureFileName string read/write Slot 2.
southEastTextureFileName string read/write Slot 3.
southTextureFileName string read/write Slot 4.
southWestTextureFileName string read/write Slot 5.
westTextureFileName string read/write Slot 6.
northWestTextureFileName string read/write Slot 7.
Method Description
GetTextureFileName(slot) The texture in slot.
SetTextureFileName(slot, fileName) Sets the texture in slot.
ClearTextureFileName(slot) Empties slot.
ClearAllTextureFileNames() Empties all eight slots.

Slots are numbered from 0, 0 (N) to 7 (NW), unlike most lists in the Lua API. A slot outside 0..7 is ignored: getters return "" and setters do nothing.

Texture paths are the same strings the inspector stores, relative to Assets with the extension, e.g. "Textures/Monsters/imp_front.png".

Any image in Assets can be switched to. When the level loads, the engine packs every .png, .jpg and .jpeg file under Assets into the texture atlas, so a script can switch to an image the level doesn't use yet. An image added to Assets while the game is running is only picked up the next time the level loads.

Examples

Flip-book animation

-- Scripts/Sprites/Animate.lua (single-direction sprite)
-- Cycles through numbered frames: Textures/Fire/fire1.png, fire2.png, ...
public string folder = "Textures/Fire/fire"
public int frameCount = 4
public number fps = 8

local t = 0
local shown = -1

function Update()
    t = t + GameTime.deltaTime
    local frame = math.floor(t * fps) % frameCount + 1

    if frame ~= shown then
        shown = frame
        entity.sprite:SetTextureFileName(0, folder .. frame .. ".png")
    end
end

Only change the texture when the frame actually changes, not every frame.

For anything more than a simple loop (a picture per direction, different timings per frame, sounds on certain frames, switching between walk and idle) use a Flipbook instead. While a Flipbook plays on a sprite, it overwrites that sprite's textures.

Flash red when hurt

-- Scripts/Sprites/HurtFlash.lua
-- Another script calls enemy:GetScript("HurtFlash"):Flash()
public number flashTime = 0.15

local timeLeft = 0

function Flash(self)
    timeLeft = flashTime
end

function Update()
    if timeLeft > 0 then
        timeLeft = timeLeft - GameTime.deltaTime
        entity.sprite.color = Vector4(1, 0.3, 0.3, 1)
    else
        entity.sprite.color = Vector4(1, 1, 1, 1)
    end
end

Face the way you walk

-- Scripts/Sprites/FaceMovement.lua (8-sided sprite on something with a Rigidbody)
function Update()
    local v = entity.rigidbody.velocity

    if Vector2(v.x, v.z).length > 1 then entity.transform:LookDirection(v) end
end

Glow pulse

-- Scripts/Sprites/Pulse.lua
public number speed = 2

local t = 0

function Update()
    t = t + GameTime.deltaTime
    local k = 0.6 + 0.4 * (mathT.Sin(t * speed * mathT.Tau) + 1) * 0.5
    entity.sprite.color = Vector4(k, k, k, 1)
end

Clone this wiki locally