raycast
Non-blocking line-of-sight and cast queries served from the cached collidable world, safe to call every frame.
Unlike physics.Raycast, which does a live blocking walk of Workspace, the raycast library answers from a cached snapshot of static collidable geometry that Conduit keeps refreshed in the background. Every function here is cheap enough to call from an onPaint or onUpdate callback.
raycast.cast
Section titled “raycast.cast”raycast.cast(origin: Vector3, direction: Vector3, [distance: number]) -> RaycastResult | nil
Casts a ray from origin along direction against the cached collidable world and returns the nearest hit as a RaycastResult (Position, Normal, Distance, Instance, Material), or nil when nothing is hit. Pass distance to cap the ray at that many studs; omit it and the ray extends to the length of direction. direction is not normalized for you, so pass a unit vector when you want distance to mean studs.
local hit = raycast.cast(camera.CFrame.Position, camera.CFrame.LookVector, 500)if hit then print(hit.Instance, hit.Position) endraycast.between
Section titled “raycast.between”raycast.between(origin: Vector3, target: Vector3) -> RaycastResult | nil
Casts a ray from origin to target and returns the nearest hit between them as a RaycastResult, or nil when the segment is clear. The ray stops at target, so this is the segment form of cast.
local hit = raycast.between(myHead, enemyHead)if not hit then print("clear line to target") endraycast.visible
Section titled “raycast.visible”raycast.visible(origin: Vector3, target: Vector3) -> boolean
Returns true when the straight line from origin to target is unobstructed. This is the terrain-aware sightline test: it accounts for terrain, opaque parts, and glass, where cast and between test collidable parts only. Use it for wall checks when you only need a yes or no answer.
if raycast.visible(myHead, enemyTorso) then -- enemyTorso is in the openendraycast.update
Section titled “raycast.update”raycast.update() -> ()
Forces the cached collidable world to re-read every tracked part now, throttled to once per second. The cache refreshes on its own, so you only need this when the world just changed (a door opened, a wall was removed) and you must query the new state this frame. Calls made within a second of the last refresh are ignored.
openTheGate()raycast.update()local hit = raycast.between(a, b)raycast.ready
Section titled “raycast.ready”raycast.ready() -> boolean
Returns true once the collidable-world cache has finished its initial build and is serving. Before this, cast and between return nil and visible returns true, because nothing is yet known to occlude. Gate aim or trigger logic on ready() so an early frame after a join or place change is not treated as a clear shot.
cheat.Register("onUpdate", function() if not raycast.ready() then return end -- visibility answers are trustworthy from hereend)