Is their a way to calculate what face of a part a raycast hit?

I’m making a ledge grab mechanic in my game, I’ve already got the raycast set up and have anchored the player. My only issue is that I’m not sure how I’m supposed to calculate the face that a raycast hit of raycast.Instance, so that I can then offset the position of the player correctly that corresponds to the correct orientation of the part.

local char = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local root = char.PrimaryPart

local origion = root.Position
local direction = root.CFrame.LookVector * 1.5

local vizual ="Part", workspace)
vizual.Anchored = true
vizual.CFrame = root.CFrame
vizual.CanCollide = false
vizual.Name = "Visualizer"

local params =
params.FilterType = Enum.RaycastFilterType.Blacklist
params.IgnoreWater = true
params.FilterDescendantsInstances = {char, vizual}

	local midpoint = origion + direction/2
	origion = root.CFrame.Position direction = root.CFrame.LookVector * 1.5
	vizual.Size =, 1, direction.Magnitude)
	vizual.CFrame =, origion)
	local ray = workspace:Raycast(origion, direction, params)  if ray then
		if ray.Instance ~= nil and ray.Instance.Name == "ledgePart" and root.Position.Y < ray.Instance.Position.Y then
			root.Anchored = true
			root.CFrame = workspace.ledgePart.CFrame -, 2, -2) -- This only works for the back of the part.
1 Like

Use the following tutorial, I found it quite helpful!


The RaycastResult contains the surface normal, in world space.


function nearestNormalId(part, direction)
    local maxDot, maxNormal = 0, nil --Exclude results <= 0
    for _, normalId in ipairs(Enum.NormalId:GetEnumItems()) do
        local normal = part.CFrame:VectorToWorldSpace(Vector3.fromNormalId(normalId))
        local dot = normal:Dot(direction) --Greater the more similar the vectors are
        if dot > 0 and dot > maxDot then
            maxDot = dot
            maxNormal = normal
    return maxNormal

This works for “normal” parts, i.e. cuboids, while the RaycastResult normal should work for meshes, unions, cylinders and spheres IIRC.


What’s the NormalId?

Also it works, tsm.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.