Razorbill
Components

Physics Components

Rigidbody

Makes an entity a dynamic physics body that responds to forces, gravity, and collisions.

PropertyTypeDefaultDescription
massFloat1.0Mass in kilograms
linear_velocityVec3{x:0, y:0, z:0}Initial linear velocity
angular_velocityVec3{x:0, y:0, z:0}Initial angular velocity (radians/second per axis)
is_kinematicBoolfalseIf true, physics doesn't move this body — scripts control it directly

Dynamic vs Kinematic

  • Dynamic (is_kinematic: false): Affected by gravity, forces, and collisions. Use for physics-driven objects like crates, balls, ragdolls.
  • Kinematic (is_kinematic: true): Moved only by scripts. Still collides with dynamic bodies. Use for moving platforms, doors, elevators.

Example: Bouncing Ball

[
  {
    "op": "CreatePrimitive",
    "params": { "primitive_type": "Sphere", "entity_name": "Ball", "position": [0, 10, 0] }
  },
  {
    "op": "AddComponent",
    "params": {
      "entity_name": "Ball",
      "component_type": "Rigidbody",
      "data": { "mass": 1.0 }
    }
  },
  {
    "op": "AddComponent",
    "params": {
      "entity_name": "Ball",
      "component_type": "Collider",
      "data": { "shape": "sphere", "params": { "radius": 0.5 } }
    }
  }
]

Scripting: Apply Forces

void OnUpdate(ScriptContext* ctx) {
    // Apply upward impulse on Space
    if (ctx->is_key_pressed(ctx, 32)) { // Space
        float impulse[3] = {0, 10, 0};
        ctx->apply_impulse(ctx, ctx->self, impulse);
    }

    // Read current velocity
    float vel[3];
    ctx->get_linear_velocity(ctx, ctx->self, vel);
}

Collider

Defines the collision shape for an entity. Required for physics interactions.

PropertyTypeDefaultDescription
shapeEnumboxShape type: box, sphere, capsule, cylinder, convex_hull
paramsNested(see below)Shape-specific parameters
offsetVec3{x:0, y:0, z:0}Offset from entity center
is_triggerBoolfalseIf true, detects overlaps without blocking movement
layerString"Default"Collision layer name for filtering

Shape Parameters

The params object contains shape-specific fields:

ShapeParameters
boxextents (Vec3) — Half-extents on each axis. Default: {x:0.5, y:0.5, z:0.5}
sphereradius (Float) — Sphere radius. Default: 0.5
capsuleradius (Float), height (Float) — Capsule dimensions
cylinderradius (Float), height (Float) — Cylinder dimensions
convex_hullmesh_guid (String) — GUID of mesh to generate hull from

Convex Hull Decomposition (V-HACD)

The convex_hull shape uses V-HACD 4.1 to automatically decompose complex meshes into a set of convex hulls for efficient physics simulation. This is especially useful for AI-generated meshes from Text-to-3D:

  • Decomposition runs asynchronously and is cached (content-addressed by mesh hash)
  • A 50-hull quality gate prevents mesh explosion on overly complex geometry
  • Results are stored in Library/ for fast retrieval after initial cooking
{
  "op": "AddComponent",
  "params": {
    "entity_name": "GeneratedModel",
    "component_type": "Collider",
    "data": {
      "shape": "convex_hull",
      "params": { "mesh_guid": "<mesh-asset-guid>" }
    }
  }
}

Triggers

Trigger colliders detect overlaps without physically blocking other objects. Use them for:

  • Pickup zones
  • Damage areas
  • Level transitions
  • Detection volumes
{
  "op": "AddComponent",
  "params": {
    "entity_name": "PickupZone",
    "component_type": "Collider",
    "data": {
      "shape": "sphere",
      "params": { "radius": 3.0 },
      "is_trigger": true
    }
  }
}

CharacterController

A full-featured character movement controller with jumping, crouching, sprinting, coyote time, and slope handling. Uses a capsule shape internally.

PropertyTypeDefaultDescription
capsule_radiusFloat0.3Capsule collision radius
capsule_heightFloat1.35Capsule height (standing)
move_speedFloat5.0Base movement speed (units/second)
jump_speedFloat6.0Initial jump velocity
max_slope_angleFloat50Maximum walkable slope in degrees
massFloat70Character mass in kg
max_strengthFloat100Force applied to push dynamic objects
step_heightFloat0.4Max step-up height for stairs
stick_to_floorFloat0.5Downward force to keep grounded on slopes
gravityFloat14.7Gravity strength
fall_gravity_multiplierFloat1.5Extra gravity when falling (snappier feel)
terminal_velocityFloat20Maximum fall speed
layerString"Default"Collision layer
crouch_heightFloat0.8Capsule height when crouching
crouch_speed_multiplierFloat0.5Speed multiplier when crouching
sprint_multiplierFloat1.5Speed multiplier when sprinting
coyote_timeFloat0.12Seconds after leaving ground where jump still works
jump_buffer_timeFloat0.12Seconds before landing where jump input is buffered
jump_cut_multiplierFloat0.5Velocity multiplier when releasing jump early (variable-height jump)

Scripting: First-Person Controller

void OnUpdate(ScriptContext* ctx) {
    float dt = ctx->get_delta_time();

    // WASD movement
    float move_x = 0, move_z = 0;
    if (ctx->is_key_down(ctx, 87)) move_z -= 1; // W
    if (ctx->is_key_down(ctx, 83)) move_z += 1; // S
    if (ctx->is_key_down(ctx, 65)) move_x -= 1; // A
    if (ctx->is_key_down(ctx, 68)) move_x += 1; // D

    float vel[3] = {move_x * 5.0f, 0, move_z * 5.0f};
    ctx->set_character_velocity(ctx, ctx->self, vel);

    // Jump
    if (ctx->is_key_pressed(ctx, 32)) { // Space
        ctx->character_jump(ctx, ctx->self);
    }

    // Sprint
    ctx->set_character_sprint(ctx, ctx->self,
        ctx->is_key_down(ctx, 340)); // Left Shift

    // Crouch
    ctx->set_character_crouch(ctx, ctx->self,
        ctx->is_key_down(ctx, 341)); // Left Ctrl
}

On this page