Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofmodule physics.module·originates fromworld 07158574-5…

walls

Wall-detection and slide helpers for the character controller. Sweeps the character's own capsule along the movement direction, probes a single height with a horizontal ray, and slides a movement vector along a wall normal. No state.

byzero-proxy @ DESKTOP-DB3UJOJ·posted 2mo ago
What it does

walls

Wall-detection and slide helpers for the character controller. Sweeps the character's own capsule along the movement direction, probes a single height with a horizontal ray, and slides a movement vector along a wall normal. No state.

Exports

  • M.castBody(x: number, y: number, z: number, dirX: number, dirZ: number, height: number, radius: number, skinWidth: number, maxSlopeAngle: number, selfId: string) -> hit? — sweep the capsule spanning the character from the top of the ground band above (x, y, z) (its feet) up to y + height, reaching skinWidth past its own surface. Returns the wall standing across the path, or nil when the path is clear.
  • M.castDirection(x: number, y: number, z: number, dirX: number, dirZ: number, radius: number, skinWidth: number, selfId: string) -> hit? — single horizontal ray of length radius + skinWidth, from whichever sample height the caller passes.
  • M.slideAlongWall(moveX: number, moveZ: number, normalX: number, normalZ: number) -> (number, number) — strip the component of move going into the wall (v - (v . n) * n, XZ only). Returns input unchanged when dot >= 0 or the XZ-normal is effectively zero.

Usage

local Walls = require("@builtin::systems.characterController.characterController.physics.walls")

local hit = Walls.castBody(px, py, pz, dirX, dirZ, 1.8, 0.3, 0.01, 45, selfId)
if hit then
    local slideX, slideZ = Walls.slideAlongWall(dx, dz, hit.normal.x, hit.normal.z)
end

Notes

  • castBody sweeps the whole body, so an opening narrower than 2 * radius stops the character even when nothing stands on the centre line — two cabinets 6 cm apart are a wall, not a doorway.
  • A contact whose surface faces up or down — the ramps the character walks up, to maxSlopeAngle, and anything directly overhead — belongs to the ground and ceiling passes. castBody sweeps on past those, so a body on a ramp still reports the wall ahead of it.
  • castBody starts its sweep above the ground band: a cap of radius resting on ground of angle a reaches radius * (1 / cos(a) - 1) below the surface uphill of it, and a sweep begun inside a surface describes the shortest way out of that overlap instead of the surface standing across the path. The band is measured at maxSlopeAngle, the steepest ground the character walks, and the ground and step passes own everything under it.
  • slideAlongWall normalises the wall normal in XZ; callers don't need to pre-normalise. The Y component of the normal is ignored because slide-along is a horizontal operation.
  • The slide helper returns the input movement unchanged whenever the movement isn't pressing into the wall — there's no "stick to wall" behaviour, only "don't pass through".

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

Walls Module Wall detection for the character controller. `castBody` sweeps the character's own capsule in the movement direction, so a passage is blocked whenever the body does not fit through it; `castDirection` probes a single height with a ray. Both return the surface normal for sliding along the wall. Pure helpers — no module state. `castBody` sweeps from above the ground band: a sweep that starts inside a surface answers about that overlap, and the answer describes the shortest way out of it rather than the surface standing across the path. Consumers: local Walls = require("@builtin::systems.characterController.characterController.physics.walls") local hit = Walls.castBody(x, y, z, dirX, dirZ, height, radius, skin, maxSlope, selfId) local mx, mz = Walls.slideAlongWall(dx, dz, hit.normal.x, hit.normal.z)

castDirection(x: number, y: number, z: number, dirX: number, dirZ: number, radius: number, skinWidth: number, selfId: string) → any

Cast a horizontal wall-detection ray from `(x, y, z)` in direction `(dirX, 0, dirZ)`. Ray length is `radius + skinWidth`.

argtypedescription
xnumberCharacter centre X.
ynumberCharacter centre Y (sample height).
znumberCharacter centre Z.
dirXnumberHorizontal direction X (normalized).
dirZnumberHorizontal direction Z (normalized).
radiusnumberCharacter capsule radius (ray starts at the centre).
skinWidthnumberExtra margin for depenetration.
selfIdstringEntity ID to exclude from the raycast.

examples

local hit = Walls.castDirection(px, py, pz, dx, dz, 0.3, 0.01, selfId)

castBody(x: number, y: number, z: number, dirX: number, dirZ: number, height: number, radius: number, skinWidth: number, maxSlopeAngle: number, selfId: string) → any

Sweep the character's capsule from `(x, y, z)` (its feet) in direction `(dirX, 0, dirZ)` and report the wall it runs into within `skinWidth` of its own surface. Because the whole body is swept, a passage narrower than `2 * radius` blocks the character even when nothing stands on its centre line. The sweep starts above the ground band — the depth a cap of `radius` reaches below ground of `maxSlopeAngle`, which is how far into the slope the body's own lower cap sits while it stands there. Below that line the surface belongs to the ground and step passes; above it the sweep runs clear of the ground and reports the outward normal of the surface standing across the path. A contact whose surface faces up or down — ramps the character walks up, to `maxSlopeAngle`, and anything directly overhead — belongs to the ground and ceiling passes. The sweep carries on past those to the surface that stands across the path. the body's path is clear.

argtypedescription
xnumberCharacter feet X.
ynumberCharacter feet Y.
znumberCharacter feet Z.
dirXnumberHorizontal movement direction X (normalized).
dirZnumberHorizontal movement direction Z (normalized).
heightnumberCharacter capsule height.
radiusnumberCharacter capsule radius.
skinWidthnumberHow far past the body's own surface the sweep reaches.
maxSlopeAnglenumberSteepest surface, in degrees, the character walks on.
selfIdstringEntity ID to exclude from the sweep.

examples

local hit = Walls.castBody(px, py, pz, dx, dz, 1.8, 0.3, 0.01, 45, selfId)

slideAlongWall(moveX: number, moveZ: number, normalX: number, normalZ: number) →

Compute a wall-slide direction given the desired horizontal movement and a wall normal. Strips the component of `move` that goes into the wall; returns the input unchanged when the movement isn't pressing into the wall (`dot >= 0`) or the normal is effectively zero in the XZ plane.

argtypedescription
moveXnumberDesired horizontal movement X.
moveZnumberDesired horizontal movement Z.
normalXnumberWall surface normal X.
normalZnumberWall surface normal Z.

examples

local mx, mz = Walls.slideAlongWall(dx, dz, nx, nz)

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

3items
·
other · born here
▤file
▲ 0↑ born

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.