Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

ground

Ground-probing and slope-math helpers for the character controller. A downward raycast helper plus two pure vector helpers (slope angle, plane projection). No state.

Exports

  • M.cast(x: number, y: number, z: number, skinWidth: number, maxDist: number, selfId: string, riseDist: number?) -> hit? — cast a ray downward from (x, y + riseDist + skinWidth, z), reaching maxDist below the feet. The returned hit's distance is adjusted to be relative to the feet, not the ray origin, and is negative for ground standing above them. The ray passes through the colliders the body carries (selfId and every entity parented under it), so a prop held at the feet is never the ground.
  • M.slopeAngle(nx: number, ny: number, nz: number) -> number — degrees between the supplied normal and world up. Returns 0 on a zero-length normal.
  • M.projectOnSlope(moveX, moveY, moveZ, normalX, normalY, normalZ) -> (number, number, number) — project a movement vector onto the plane perpendicular to a normal: v - (v . n) * n.

Usage

local Ground = require("@builtin::systems.characterController.characterController.physics.ground")

local hit = Ground.cast(px, py, pz, 0.01, 0.2, selfId)
if hit then
    local angle = Ground.slopeAngle(hit.normal.x, hit.normal.y, hit.normal.z)
    if angle <= 45 then
        -- walkable
    end
end

local px, py, pz = Ground.projectOnSlope(dx, 0, dz, nx, ny, nz)

Notes

  • cast shifts the origin up by skinWidth to avoid starting the ray inside the ground when the character is sitting on a contact, then subtracts skinWidth back off hit.distance so callers see the true distance from the feet.
  • riseDist raises the origin further, so the ray also covers ground that stands above the feet — the ground a walking character climbs into. A hit up there reports a negative distance: how far the character rises to stand on it.
  • slopeAngle clamps cos(angle) into [-1, 1] before acos — callers don't need to normalise the input.
  • projectOnSlope does not normalise the surface normal; callers should pass a unit normal (raycast normals already are).