4 min read

Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.

Raycasting

At its most basic level, raycasting is the act of sending out an invisible ray from a Vector3 point in a specific direction with a defined length. Once cast, you can detect if the ray hits a BasePart or Terrain cell.

Lasers are fired by floating orbs, and raycasting determines whether a laser hits a platform. Platforms touched by the lasers are temporarily destroyed.

You can cast a ray with the WorldRoot:Raycast() method (Workspace:Raycast()) from a Vector3 origin in a Vector3 direction.

local Workspace = game:GetService("Workspace")

local rayOrigin = Vector3.new(0, 0, 0)
local rayDirection = Vector3.new(0, -100, 0)

local raycastResult = Workspace:Raycast(rayOrigin, rayDirection)

Note

When casting a ray, the direction parameter should encompass the desired length of the ray. For instance, if the magnitude of the direction is 10, the resulting ray will also be of length 10. The maximum length is 15,000 studs.

When applicable, you can calculate an unknown directional vector (rayDirection) using a known origin and destination. This is useful when casting a ray between two points that can change, such as from one player character to another.

  1. The origin plus a directional vector indicate the ray's destination:

    $\text{rayOrigin} + \text{rayDirection} = \text{rayDestination}$

  2. Subtract $\text{rayOrigin}$ from both sides of the equation:

    $\text{rayOrigin} + \text{rayDirection} - \text{rayOrigin} = \text{rayDestination} - \text{rayOrigin}$

  3. The ray's direction equals the destination minus the origin:

    $\text{rayDirection} = \text{rayDestination} - \text{rayOrigin}$

local Workspace = game:GetService("Workspace")

local rayOrigin = Workspace.TestOrigin.Position
local rayDestination = Workspace.TestDestination.Position

local rayDirection = rayDestination - rayOrigin

local raycastResult = Workspace:Raycast(rayOrigin, rayDirection)

Filter options

WorldRoot:Raycast() accepts an optional RaycastParams object which tells the raycast to selectively include or exclude certain BaseParts, ignore the Water material for Terrain, or use a collision group.

Key Description
`FilterDescendantsInstances` `Array` of objects whose descendants are used in filtering raycasting candidates.
`FilterType` [`RaycastFilterType`](/docs/enum-raycastfiltertype) enum which determines how the `FilterDescendantsInstances` array is used in the raycast operation.
  • [`Exclude`](/docs/enum-raycastfiltertype) — Every [`BasePart`](/docs/basepart) is considered **except** those that are descendants of objects in the array.
  • [`Include`](/docs/enum-raycastfiltertype) — Only [`BaseParts`](/docs/basepart) that are descendants of objects in the array are considered.
`IgnoreWater` Boolean which determines whether the **Water** material is considered when raycasting against [`Terrain`](/docs/terrain).
`CollisionGroup` String name of the [collision group](/docs/roblox-workspace-collisions#collision-filtering) used for the raycasting operation.
local Workspace = game:GetService("Workspace")

local rayOrigin = Vector3.zero
local rayDirection = Vector3.new(0, -100, 0)

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {script.Parent}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.IgnoreWater = true

local raycastResult = Workspace:Raycast(rayOrigin, rayDirection, raycastParams)

Hit detection

If the raycasting operation hits an eligible BasePart or Terrain cell, a RaycastResult object is returned containing the results. To test for a hit, confirm that the result is not nil and utilize the following properties as needed.

Property Description
[`Instance`](/docs/instance) The [`BasePart`](/docs/basepart) or [`Terrain`](/docs/terrain) cell that the ray intersected.
`Position` [`Vector3`](/docs/vector3) position of the intersection between the ray and the [`Instance`](/docs/instance).
`Distance` Distance between the ray origin and intersection point.
`Material` The [`Material`](/docs/enum-material) of the [`BasePart`](/docs/basepart) or [`Terrain`](/docs/terrain) at the intersection point.
`Normal` [`Vector3`](/docs/vector3) of the normal vector of the intersected face.

Note

When used in a place with instance streaming enabled, a client may not have streamed in distant BaseParts, so a raycast may not detect a hit. Additionally, low-detail "imposter" Terrain and Models generated by the streaming system are purely visual and are not eligible raycast targets.

Note

You can exempt any BasePart from hit detection by setting its BasePart.CanQuery property to false.

local Workspace = game:GetService("Workspace")

local rayOrigin = Vector3.zero
local rayDirection = Vector3.new(0, -100, 0)

local raycastResult = Workspace:Raycast(rayOrigin, rayDirection)

if raycastResult then
	print("Instance:", raycastResult.Instance)
	print("Position:", raycastResult.Position)
	print("Distance:", raycastResult.Distance)
	print("Material:", raycastResult.Material)
	print("Normal:", raycastResult.Normal)
else
	warn("No raycast result!")
end