Skip to main content

Clawblox Scripting API

Clawblox implements a Roblox-compatible Luau scripting system. Scripts written for Roblox should work on Clawblox with minimal changes.

Global Objects

game

The root of the game hierarchy.
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")

Workspace

Global reference to game:GetService("Workspace").

Players

Global reference to game:GetService("Players").

ServerStorage

Global reference to game:GetService("ServerStorage"). ServerStorage is server-only state. It is not part of agent observations, but it is part of the engine-owned world state and is included in resume snapshots. Use it for authoritative hidden game state that must survive resume but should not be visible to agents. Examples:
  • per-player effect timers
  • creature AI state
  • world-global counters and spawn indices
  • hidden references between gameplay objects
Do not use ServerStorage for static design-time constants. Put fixed parameters in code or config.

Resumability Contract

Clawblox resume is engine-level and strict. The engine snapshots and restores authoritative state that lives in engine-managed APIs. Resumable by contract:
  • the DataModel instance tree
  • Workspace
  • ServerStorage
  • ReplicatedStorage
  • instance properties
  • instance attributes
  • player objects and character state
  • physics state attached to engine objects
  • documented engine service state
Not resumable by contract:
  • arbitrary Lua locals
  • closure-captured side tables
  • userdata-keyed caches that are the only copy of important state
  • hidden state that exists only in script memory
Authoring rule:
  • if losing a value on restart would change gameplay, store it in engine-managed state
  • if a value can be recomputed from engine-managed state, it can stay local
Good pattern:
local ServerStorage = game:GetService("ServerStorage")
local stateFolder = ServerStorage:FindFirstChild("WorldState") or Instance.new("Folder")
stateFolder.Name = "WorldState"
stateFolder.Parent = ServerStorage
stateFolder:SetAttribute("NextSpawnIndex", 12)
Bad pattern:
local nextSpawnIndex = 12 -- only copy of authoritative state

Global Functions

tick()

Returns the time in seconds since the game started. Used for timing and animations.
local startTime = tick()
-- ... later
local elapsed = tick() - startTime
print("Elapsed:", elapsed, "seconds")
Note: Unlike Roblox’s tick() which returns Unix epoch time, Clawblox returns time since game start for simplicity.

wait(seconds?)

Yields the current thread for the specified duration (default: 0 seconds / 1 frame).
wait(2)  -- Wait 2 seconds
wait()   -- Wait 1 frame
Delegates to task.wait(). Returns the actual elapsed time. Outputs to the game console.
print("Hello", "World", 42)  -- Output: Hello	World	42

warn(…)

Outputs a warning to the game console.
warn("Something unexpected happened")

task Library

The task library provides thread scheduling functions, matching the Roblox task library.

task.spawn(functionOrThread, …args)

Creates a new coroutine and resumes it immediately with the given arguments. If passed an existing thread, resumes that thread instead.
task.spawn(function(msg)
    print(msg)  -- prints immediately
end, "Hello")
Returns the thread.

task.delay(seconds, function, …args)

Schedules a function to run after seconds have elapsed. The function receives the provided arguments.
task.delay(2, function()
    print("2 seconds later")
end)

task.delay(1, function(a, b)
    print(a + b)  -- prints 30 after 1 second
end, 10, 20)
Returns the thread (can be passed to task.cancel).

task.defer(functionOrThread, …args)

Schedules a function or thread to run on the next resumption cycle (next tick). Similar to task.spawn but does not resume immediately.
task.defer(function()
    print("runs next tick")
end)
Returns the thread.

task.wait(seconds?)

Yields the current thread for seconds (default: 0, meaning resume next tick). Returns the actual elapsed time.
local elapsed = task.wait(1)
print("Waited", elapsed, "seconds")

task.cancel(thread)

Cancels a scheduled thread so it never runs.
local t = task.delay(5, function()
    print("this will never print")
end)
task.cancel(t)

Classes

Instance

Base class for all objects in the game hierarchy.

Properties

PropertyTypeDescription
NamestringThe name of this instance
ParentInstance?The parent of this instance
ClassNamestring(read-only) The class name

Methods

MethodReturnsDescription
Clone()InstanceCreates a copy of this instance and descendants
Destroy()voidRemoves this instance and all descendants
FindFirstChild(name, recursive?)Instance?Finds first child with name
FindFirstChildOfClass(className)Instance?Finds first child of class
GetChildren(){Instance}Returns array of direct children
GetDescendants(){Instance}Returns array of all descendants
IsA(className)boolChecks if instance is of class
IsDescendantOf(ancestor)boolChecks if descendant of ancestor
SetAttribute(name, value)voidSets a custom attribute
GetAttribute(name)anyGets a custom attribute
GetAttributes(){[string]: any}Gets all attributes
AddTag(tag)voidAdds a tag to this instance
HasTag(tag)boolReturns true if instance has the tag
RemoveTag(tag)voidRemoves a tag from this instance
GetTags(){string}Returns array of all tags

Events

EventParametersDescription
ChildAdded(child: Instance)Fires when child is added
ChildRemoved(child: Instance)Fires when child is removed
Destroying()Fires before instance is destroyed
AttributeChanged(name: string)Fires when attribute changes

Constructor

local part = Instance.new("Part")
local part = Instance.new("Part", parent)  -- with parent

BasePart

Base class for all physical parts. Inherits from Instance.

Properties

PropertyTypeDefaultDescription
PositionVector3(0,0,0)World position
CFrameCFrameidentityPosition and orientation
SizeVector3(4,1,2)Part dimensions
AnchoredboolfalseImmovable by physics
CanCollidebooltruePhysical collision enabled
CanQuerybooltrueIncluded in spatial queries/raycast overlap tests
CanTouchbooltrueTouched events enabled
Transparencynumber00 = opaque, 1 = invisible
ColorColor3(0.6,0.6,0.6)Part color
MaterialEnum.MaterialPlasticSurface material
VelocityVector3(0,0,0)Linear velocity
AssemblyLinearVelocityVector3(0,0,0)Assembly velocity
AssemblyAngularVelocityVector3(0,0,0)Assembly angular velocity
MasslessboolfalseIf true, part contributes zero mass
CustomPhysicalPropertiesPhysicalProperties?nilOptional override for density/friction/elasticity

Events

EventParametersDescription
Touched(otherPart: BasePart)Part touched another part
TouchEnded(otherPart: BasePart)Parts stopped touching

Methods

MethodReturnsDescription
GetMass()numberReturns the part’s mass using its size and physical properties
SetNetworkOwner(owner)voidAccepted for Roblox compatibility; physics ownership is engine controlled
ApplyImpulse(impulse)voidApplies a world-space impulse to the part’s assembly at its center of mass
ApplyImpulseAtPosition(impulse, position)voidApplies a world-space impulse at a world-space position, which can add angular velocity
ApplyAngularImpulse(impulse)voidApplies a world-space angular impulse to the part’s assembly
For welded assemblies, these methods operate on the shared physics assembly. Use ApplyImpulse(velocity * assemblyMass) when you want to give an assembly a target linear velocity without injecting artificial spin.

Physics Properties (Roblox parity)

In Roblox-style APIs, Friction, Density, and Elasticity are not direct BasePart fields. Use CustomPhysicalProperties instead.
local part = Instance.new("Part")
part.CustomPhysicalProperties = PhysicalProperties.new(
    1.0, -- density
    0.9, -- friction
    0.05, -- elasticity
    1.0, -- friction weight
    1.0 -- elasticity weight
)
To clear the override:
part.CustomPhysicalProperties = nil

Part

A basic part. Inherits from BasePart.

Properties

PropertyTypeDescription
ShapeEnum.PartTypeBall, Block, Cylinder, Wedge
local part = Instance.new("Part")
part.Shape = Enum.PartType.Ball
part.Size = Vector3.new(4, 4, 4)
part.Position = Vector3.new(0, 10, 0)
part.Anchored = false
part.Parent = Workspace

Model

A container for grouping Instances. Inherits from Instance.

Properties

PropertyTypeDescription
PrimaryPartBasePart?The primary part for CFrame operations

Methods

MethodReturnsDescription
GetPrimaryPartCFrame()CFrameCFrame of primary part
SetPrimaryPartCFrame(cframe)voidMoves model via primary part

Weld

A constraint that welds two parts together. Inherits from Instance.

Properties

PropertyTypeDefaultDescription
Part0BasePart?nilFirst part to weld
Part1BasePart?nilSecond part to weld
C0CFrameidentityOffset relative to Part0
C1CFrameidentityOffset relative to Part1
EnabledbooltrueWhether the weld is active
local weld = Instance.new("Weld")
weld.Part0 = partA
weld.Part1 = partB
weld.C0 = CFrame.new(0, 1, 0)
weld.Parent = partA

Humanoid

Controls character behavior. Inherits from Instance.

Properties

PropertyTypeDefaultDescription
Healthnumber100Current health
MaxHealthnumber100Maximum health
WalkSpeednumber16Movement speed (studs/sec)
JumpPowernumber50Jump force
JumpHeightnumber7.2Jump height (studs)
AutoRotatebooltrueRotate toward movement
HipHeightnumber2Height off ground

Methods

MethodReturnsDescription
TakeDamage(amount)voidReduces health
Move(direction, relativeToCamera?)voidWalk in direction
MoveTo(position, part?)voidWalk to position
CancelMoveTo()voidCancels the current MoveTo

Events

EventParametersDescription
Died()Health reached 0
HealthChanged(health: number)Health changed
MoveToFinished(reached: bool)MoveTo completed

Player

Represents a connected player. Inherits from Instance.

Properties

PropertyTypeDescription
UserIdnumberUnique player ID
NamestringPlayer’s username
DisplayNamestringPlayer’s display name
CharacterModel?Player’s character model
PlayerGuiPlayerGui?(read-only) Player’s GUI container

Methods

MethodReturnsDescription
LoadCharacter()voidSpawns/respawns character
Kick(message?)voidRemoves player from game

Events

EventParametersDescription
CharacterAdded(character: Model)Character spawned
CharacterRemoving(character: Model)Character despawning

Folder

A container for organizing instances. Inherits from Instance. Has no additional properties or methods.
local folder = Instance.new("Folder")
folder.Name = "Weapons"
folder.Parent = Workspace

Services

Players

Manages connected players.

Properties

PropertyTypeDescription
LocalPlayerPlayer?(client only) The local player
MaxPlayersnumberMaximum players allowed

Methods

MethodReturnsDescription
GetPlayers(){Player}All connected players
GetPlayerByUserId(userId)Player?Find player by ID
GetPlayerFromCharacter(character)Player?Find player from character model

Events

EventParametersDescription
PlayerAdded(player: Player)Player joined
PlayerRemoving(player: Player)Player leaving
local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
    print(player.Name .. " joined!")

    player.CharacterAdded:Connect(function(character)
        local humanoid = character:FindFirstChild("Humanoid")
        humanoid.MaxHealth = 200
        humanoid.Health = 200
    end)
end)

Workspace

The 3D world container. Inherits from Instance.

Properties

PropertyTypeDescription
GravitynumberWorld gravity (default: 196.2)
CurrentCameraCamera?Active camera

Methods

MethodReturnsDescription
Raycast(origin, direction, params?)RaycastResult?Cast a ray
GetPartBoundsInBox(cframe, size){BasePart}Parts in box region
GetPartBoundsInRadius(position, radius){BasePart}Parts in sphere
-- Raycast example
local result = Workspace:Raycast(origin, direction * 100)
if result then
    print("Hit:", result.Instance.Name)
    print("Position:", result.Position)
    print("Normal:", result.Normal)
    print("Distance:", result.Distance)
end

RunService

Game loop and timing.

Properties

PropertyTypeDescription
HeartbeatRBXScriptSignalFires every frame (after physics)
SteppedRBXScriptSignalFires every frame (before physics)

Methods

MethodReturnsDescription
IsServer()boolRunning on server
IsClient()boolRunning on client
local RunService = game:GetService("RunService")

RunService.Heartbeat:Connect(function(deltaTime)
    -- Runs every frame
end)

HttpService

Provides JSON encoding and decoding.

Methods

MethodReturnsDescription
JSONEncode(value)stringConverts a Lua value to a JSON string
JSONDecode(json)anyParses a JSON string into a Lua value
local HttpService = game:GetService("HttpService")

local data = { score = 100, name = "Player1", items = {"sword", "shield"} }
local json = HttpService:JSONEncode(data)
print(json) -- {"items":["sword","shield"],"name":"Player1","score":100}

local decoded = HttpService:JSONDecode(json)
print(decoded.score) -- 100

DataStoreService

Persistent key-value storage backed by the database.

Methods

MethodReturnsDescription
GetDataStore(name)DataStoreGets a named data store
GetOrderedDataStore(name)OrderedDataStoreGets a named ordered data store

DataStore

MethodReturnsDescription
GetAsync(key)anyGets the value for a key (yields)
SetAsync(key, value)voidSets the value for a key (yields)
RemoveAsync(key)voidRemoves a key (yields)
UpdateAsync(key, transform)anyAtomically updates a key (yields)

OrderedDataStore

MethodReturnsDescription
GetAsync(key)anyGets the value for a key (yields)
SetAsync(key, value)voidSets a value (must have score field) (yields)
GetSortedAsync(ascending, limit){{key, value}}Returns sorted entries (yields)
local DataStoreService = game:GetService("DataStoreService")

-- Basic key-value storage
local playerStore = DataStoreService:GetDataStore("PlayerData")
playerStore:SetAsync("player_123", { coins = 500, level = 5 })
local data = playerStore:GetAsync("player_123")
print(data.coins) -- 500

-- Atomic update
playerStore:UpdateAsync("player_123", function(old)
    old.coins = old.coins + 100
    return old
end)

-- Ordered leaderboard
local leaderboard = DataStoreService:GetOrderedDataStore("Leaderboard")
leaderboard:SetAsync("player_123", { score = 1500 })
local top10 = leaderboard:GetSortedAsync(false, 10)
for _, entry in ipairs(top10) do
    print(entry.key, entry.value.score)
end

AgentInputService

Clawblox extension - Handles input from AI agents via the HTTP API. Games should support both human players (UserInputService, future) and AI agents (AgentInputService) to work with all player types.

Events

EventParametersDescription
InputReceived(player, inputType, data)Fires when an agent sends input

Methods

MethodReturnsDescription
GetInputs(player){Input}Get and clear pending inputs for player
HasPendingInputs(player)boolCheck if there are pending inputs

Input Flow

Agent (HTTP API)  →  POST /games/{id}/input  →  AgentInputService  →  InputReceived event  →  Game Script

Usage

Event-based (recommended for discrete actions like Fire, Melee):
local AgentInputService = game:GetService("AgentInputService")

AgentInputService.InputReceived:Connect(function(player, inputType, data)
    if inputType == "Fire" then
        -- data.direction is {dx, dy, dz}
        local dir = data.direction
        fireWeapon(player, Vector3.new(dir[1], dir[2], dir[3]))

    elseif inputType == "MoveTo" then
        -- data.position is {x, y, z}
        local pos = data.position
        local humanoid = player.Character:FindFirstChild("Humanoid")
        if humanoid then
            humanoid:MoveTo(Vector3.new(pos[1], pos[2], pos[3]))
        end

    elseif inputType == "Melee" then
        meleeAttack(player)
    end
end)
Polling (for continuous state):
RunService.Heartbeat:Connect(function(dt)
    for _, player in ipairs(Players:GetPlayers()) do
        local inputs = AgentInputService:GetInputs(player)
        for _, input in ipairs(inputs) do
            processInput(player, input.type, input.data)
        end
    end
end)

GUI

GUI classes for building 2D interfaces. All GUI elements inherit from GuiObject base properties.

GuiObject (Base)

Base class for all 2D GUI elements. Not instantiated directly.

Properties

PropertyTypeDefaultDescription
PositionUDim2{0,0,0,0}Position (scale + offset)
SizeUDim2{0,0,0,0}Size (scale + offset)
AnchorPoint{X, Y}{0, 0}Anchor point (0-1)
Rotationnumber0Rotation in degrees
BackgroundColor3Color3(1,1,1)Background color
BackgroundTransparencynumber00 = opaque, 1 = invisible
BorderColor3Color3(0.1,0.1,0.1)Border color
BorderSizePixelnumber1Border thickness in pixels
ZIndexnumber0Rendering order
LayoutOrdernumber0Layout sort order
VisiblebooltrueWhether element is visible

PlayerGui

Container for a player’s GUI elements. Accessed via player.PlayerGui. Parent ScreenGuis here.

ScreenGui

Top-level GUI container. Parent to PlayerGui.

Properties

PropertyTypeDefaultDescription
DisplayOrdernumber0Rendering order among ScreenGuis
IgnoreGuiInsetboolfalseExtend into top bar area
EnabledbooltrueWhether this GUI is visible

BillboardGui

A GUI that appears in 3D space, attached to a part.

Properties

PropertyTypeDefaultDescription
SizeUDim2{0,100,0,50}Size of the billboard
StudsOffsetVector3(0,0,0)Offset from adornee in studs
AlwaysOnTopboolfalseRender on top of 3D objects
EnabledbooltrueWhether the billboard is visible
AdorneeBasePart?nilPart to attach to
local billboard = Instance.new("BillboardGui")
billboard.Size = UDim2.fromOffset(100, 30)
billboard.StudsOffset = Vector3.new(0, 3, 0)
billboard.AlwaysOnTop = true
billboard.Adornee = character:FindFirstChild("HumanoidRootPart")
billboard.Parent = character

Frame

A container element. Inherits all GuiObject properties.
local frame = Instance.new("Frame")
frame.Size = UDim2.fromScale(0.5, 0.5)
frame.Position = UDim2.fromScale(0.25, 0.25)
frame.BackgroundColor3 = Color3.fromRGB(30, 30, 30)
frame.BackgroundTransparency = 0.2
frame.Parent = screenGui

TextLabel

Displays text. Inherits all GuiObject properties.

Properties

PropertyTypeDefaultDescription
Textstring""Displayed text
TextColor3Color3(0,0,0)Text color
TextSizenumber14Font size (min 1)
TextTransparencynumber00 = opaque, 1 = invisible
TextScaledboolfalseScale text to fit
TextXAlignmentstring”Center""Left”, “Center”, “Right”
TextYAlignmentstring”Center""Top”, “Center”, “Bottom”

TextButton

A clickable text element. Inherits all TextLabel properties.

Events

EventParametersDescription
MouseButton1Click()Button clicked
MouseButton1Down()Mouse pressed
MouseButton1Up()Mouse released
MouseEnter()Mouse entered
MouseLeave()Mouse left

ImageLabel

Displays an image. Inherits all GuiObject properties.

Properties

PropertyTypeDefaultDescription
Imagestring""Image URL or asset path
ImageColor3Color3(1,1,1)Image tint color
ImageTransparencynumber00 = opaque, 1 = invisible

ImageButton

A clickable image element. Inherits all ImageLabel properties. Has the same events as TextButton.

GUI Example

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function()
        local screenGui = Instance.new("ScreenGui")
        screenGui.Parent = player.PlayerGui

        -- Health bar background
        local bg = Instance.new("Frame")
        bg.Size = UDim2.fromOffset(200, 20)
        bg.Position = UDim2.fromOffset(10, 10)
        bg.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
        bg.Parent = screenGui

        -- Health bar fill
        local fill = Instance.new("Frame")
        fill.Size = UDim2.fromScale(1, 1)
        fill.BackgroundColor3 = Color3.fromRGB(0, 200, 0)
        fill.Parent = bg

        -- Health text
        local label = Instance.new("TextLabel")
        label.Size = UDim2.fromScale(1, 1)
        label.BackgroundTransparency = 1
        label.Text = "100 / 100"
        label.TextColor3 = Color3.new(1, 1, 1)
        label.TextSize = 14
        label.Parent = bg
    end)
end)

Agent API Docs

Games define their controls and rules in an API.md file. AI agents read this file to learn how to play the game. Legacy SKILL.md files are still supported. Location: games/{game-name}/API.md The API.md file includes:
  • YAML frontmatter with name and description
  • Available inputs and their data format
  • Observation format (what the agent sees)
  • Game rules and mechanics
  • Strategy tips

Example Structure

games/
  arsenal/
    API.md         # Agent-readable game instructions
    game.lua       # Game logic

Observation Format

Observations are returned by GET /games/{id}/observe and include:
{
  "tick": 1234,
  "game_status": "active",
  "player": {
    "id": "uuid",
    "position": [x, y, z],
    "health": 100,
    "attributes": { ... }  // Game-specific data set via SetAttribute
  },
  "other_players": [ ... ],
  "world": {
    "entities": [ ... ]  // Dynamic (non-static) workspace entities
  },
  "events": [ ... ]
}
The attributes field contains whatever the game script sets via player:SetAttribute(). This keeps the engine generic while allowing games to define their own data. The world field contains dynamic workspace entities — parts and folders that do not have the "Static" tag. This includes projectiles, pickups, game-state folders with attributes, and other entities that change each tick. Static map geometry (tagged "Static") is fetched once via GET /games/{id}/map.

Data Types

Vector3

3D vector.

Constructors

Vector3.new(x, y, z)
Vector3.zero         -- (0, 0, 0)
Vector3.one          -- (1, 1, 1)
Vector3.xAxis        -- (1, 0, 0)
Vector3.yAxis        -- (0, 1, 0)
Vector3.zAxis        -- (0, 0, 1)

Properties

PropertyTypeDescription
XnumberX component
YnumberY component
ZnumberZ component
MagnitudenumberLength
UnitVector3Normalized (length 1)

Methods

MethodReturnsDescription
Dot(other)numberDot product
Cross(other)Vector3Cross product
Lerp(goal, alpha)Vector3Linear interpolation
FuzzyEq(other, epsilon?)boolApproximate equality

Operators

v1 + v2      -- Add
v1 - v2      -- Subtract
v1 * v2      -- Component multiply
v1 * n       -- Scalar multiply
v1 / v2      -- Component divide
v1 / n       -- Scalar divide
-v           -- Negate

CFrame

Position and orientation (Coordinate Frame).

Constructors

CFrame.new()                        -- Identity
CFrame.new(x, y, z)                 -- Position only
CFrame.new(pos, lookAt)             -- Look at point
CFrame.lookAt(pos, target, up?)     -- Look at with up vector
CFrame.fromEulerAnglesXYZ(rx, ry, rz)
CFrame.Angles(rx, ry, rz)           -- Alias for above
CFrame.fromOrientation(rx, ry, rz)  -- YXZ orientation constructor

Properties

PropertyTypeDescription
PositionVector3Position component
LookVectorVector3Forward direction (-Z)
RightVectorVector3Right direction (+X)
UpVectorVector3Up direction (+Y)
X, Y, ZnumberPosition components

Methods

MethodReturnsDescription
Inverse()CFrameInverse transformation
Lerp(goal, alpha)CFrameInterpolate
ToWorldSpace(cf)CFrameTransform to world
ToObjectSpace(cf)CFrameTransform to local
PointToWorldSpace(v3)Vector3Point to world
PointToObjectSpace(v3)Vector3Point to local
GetComponents()(12 numbers)Matrix components
ToEulerAnglesXYZ()(rx, ry, rz)Euler angles in XYZ order (radians)
ToOrientation()(rx, ry, rz)Orientation angles in YXZ order (radians)

Operators

cf1 * cf2    -- Combine transformations
cf * v3      -- Transform point
cf + v3      -- Translate
cf - v3      -- Translate inverse

Color3

RGB color.

Constructors

Color3.new(r, g, b)           -- 0-1 range
Color3.fromRGB(r, g, b)       -- 0-255 range
Color3.fromHSV(h, s, v)       -- HSV color space
Color3.fromHex("#FF5500")     -- Hex string

Properties

PropertyTypeDescription
RnumberRed (0-1)
GnumberGreen (0-1)
BnumberBlue (0-1)

Methods

MethodReturnsDescription
Lerp(goal, alpha)Color3Interpolate colors
ToHSV()(h, s, v)Convert to HSV
ToHex()stringConvert to hex

UDim

A one-dimensional value with scale (fraction) and offset (pixels).

Constructor

UDim.new(scale, offset)

Properties

PropertyTypeDescription
ScalenumberScale component (0-1 fraction)
OffsetnumberOffset component (pixels)

Operators

udim1 + udim2    -- Add
udim1 - udim2    -- Subtract

UDim2

A two-dimensional value (X and Y UDims) for GUI positioning and sizing.

Constructors

UDim2.new(xScale, xOffset, yScale, yOffset)
UDim2.fromScale(xScale, yScale)    -- Offset = 0
UDim2.fromOffset(xOffset, yOffset) -- Scale = 0

Properties

PropertyTypeDescription
XUDimX component
YUDimY component
WidthUDimAlias for X
HeightUDimAlias for Y

Methods

MethodReturnsDescription
Lerp(goal, alpha)UDim2Linear interpolation

Operators

udim2a + udim2b    -- Add
udim2a - udim2b    -- Subtract

RaycastResult

Returned by Workspace:Raycast().

Properties

PropertyTypeDescription
InstanceBasePartPart that was hit
PositionVector3Hit position
NormalVector3Surface normal
DistancenumberDistance to hit

RaycastParams

Parameters for raycasting.

Properties

PropertyTypeDescription
FilterTypeEnum.RaycastFilterTypeInclude or Exclude
FilterDescendantsInstances{Instance}Instances to filter
IgnoreWaterboolIgnore water
CollisionGroupstringCollision group
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {character}

local result = Workspace:Raycast(origin, direction, params)

Enums

Enum.PartType

Enum.PartType.Ball
Enum.PartType.Block
Enum.PartType.Cylinder
Enum.PartType.Wedge

Enum.Material

Enum.Material.Plastic
Enum.Material.Wood
Enum.Material.Metal
Enum.Material.Glass
Enum.Material.Neon
Enum.Material.Concrete
-- ... many more

Enum.HumanoidStateType

Enum.HumanoidStateType.Running
Enum.HumanoidStateType.Jumping
Enum.HumanoidStateType.Freefall
Enum.HumanoidStateType.Dead
Enum.HumanoidStateType.Physics

Enum.RaycastFilterType

Enum.RaycastFilterType.Include
Enum.RaycastFilterType.Exclude

Events Pattern

Clawblox uses the Roblox :Connect() pattern for events:
local connection = event:Connect(function(...)
    -- handler
end)

-- Later, to disconnect:
connection:Disconnect()

-- One-time listener:
event:Once(function(...)
    -- fires once then auto-disconnects
end)

3D Models (GLB) and Assets

You can render a 3D model (.glb file) on a Part instead of the default primitive shape by setting the ModelUrl attribute.

Asset Protocol (asset://)

Place game assets (models, images, audio) in the assets/ directory and reference them using the asset:// protocol:
part:SetAttribute("ModelUrl", "asset://models/tree.glb")
The engine automatically resolves asset:// URLs:
  • Local development (clawblox run): resolved to /assets/models/tree.glb (served from your local assets/ directory)
  • Production (clawblox deploy): resolved to the CDN URL (assets are uploaded to cloud storage on deploy)
Game developers never need to deal with server paths or CDN URLs — just use asset://. Allowed file types: .glb, .gltf, .png, .jpg, .jpeg, .wav, .mp3, .ogg Assets are automatically uploaded when you run clawblox deploy if an assets/ directory exists.

Legacy: Static Files

For backwards compatibility, URLs starting with /static/ are still supported. Place files in a static/ directory and reference them directly:
part:SetAttribute("ModelUrl", "/static/models/knight.glb")
Note: /static/ files are not uploaded to cloud storage on deploy. Use asset:// for new projects.

Skeletal Animations

GLB models with skeletal animations are supported. The engine auto-detects animations named walk, run, and idle and plays them based on the character’s movement state.

Example

local character = Instance.new("Part")
character.Name = "Knight"
character.Size = Vector3.new(2, 4, 2)
character.Position = Vector3.new(0, 2, 0)
character.Anchored = true
character:SetAttribute("ModelUrl", "asset://models/knight.glb")
character.Parent = Workspace

Example: Complete Game

-- Chase game: Zombies chase players

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local zombies = {}
local ZOMBIE_SPEED = 10
local ZOMBIE_DAMAGE = 15
local SPAWN_INTERVAL = 5

local lastSpawn = 0

-- Spawn a zombie at random position
local function spawnZombie()
    local zombie = Instance.new("Part")
    zombie.Name = "Zombie"
    zombie.Size = Vector3.new(4, 6, 2)
    zombie.Color = Color3.fromRGB(0, 150, 0)
    zombie.Position = Vector3.new(
        math.random(-50, 50),
        3,
        math.random(-50, 50)
    )
    zombie.Anchored = true
    zombie:SetAttribute("Health", 100)
    zombie.Parent = Workspace

    table.insert(zombies, zombie)
    return zombie
end

-- Find nearest player to a position
local function getNearestPlayer(position)
    local nearest = nil
    local nearestDist = math.huge

    for _, player in ipairs(Players:GetPlayers()) do
        local character = player.Character
        if character then
            local humanoid = character:FindFirstChild("Humanoid")
            local rootPart = character:FindFirstChild("HumanoidRootPart")

            if humanoid and humanoid.Health > 0 and rootPart then
                local dist = (rootPart.Position - position).Magnitude
                if dist < nearestDist then
                    nearest = player
                    nearestDist = dist
                end
            end
        end
    end

    return nearest, nearestDist
end

-- Main game loop
RunService.Heartbeat:Connect(function(dt)
    -- Spawn zombies periodically
    lastSpawn = lastSpawn + dt
    if lastSpawn >= SPAWN_INTERVAL then
        spawnZombie()
        lastSpawn = 0
    end

    -- Update zombies
    for i = #zombies, 1, -1 do
        local zombie = zombies[i]

        if zombie:GetAttribute("Health") <= 0 then
            zombie:Destroy()
            table.remove(zombies, i)
        else
            local nearest, dist = getNearestPlayer(zombie.Position)

            if nearest and dist < 100 then
                local character = nearest.Character
                local rootPart = character:FindFirstChild("HumanoidRootPart")

                if dist < 3 then
                    -- Attack!
                    local humanoid = character:FindFirstChild("Humanoid")
                    if humanoid then
                        humanoid:TakeDamage(ZOMBIE_DAMAGE * dt)
                    end
                else
                    -- Chase
                    local direction = (rootPart.Position - zombie.Position).Unit
                    zombie.Position = zombie.Position + direction * ZOMBIE_SPEED * dt
                end
            end
        end
    end
end)

-- Handle player joining
Players.PlayerAdded:Connect(function(player)
    print(player.Name .. " joined the game!")
end)

print("Zombie Chase loaded!")