Getting a part's face from Raycasting?

I want to get the face of the part the player is facing with a raycast if that’s possible. I’m trying to make a ledge climbing system where the player would jump and climb edges.

I have heard about face normal with raycasting but don’t know how I could use that to help me get the actual face(to then get the edges)

Here is the code I have right now

Remotes.TestFunction.OnClientInvoke = function(part,normal)
				print("[PLAYER IS CLIMBING]")
				warn(part)
				local topSurface = part.CFrame * CFrame.new(0,(part.Size.Y/2),0) -- gets the top face of the part

				local edges = {} -- table for storing corners position and how far the edge is from the player

				-- corners positions
				local leftEdge1 = topSurface * CFrame.new((part.Size.X/-2),(part.Size.Y/2),(part.Size.Z/-2))
				local leftEdge2 = topSurface * CFrame.new((part.Size.X/-2),(part.Size.Y/2),(part.Size.Z/2))
				local rightEdge1 = topSurface * CFrame.new((part.Size.X/2),(part.Size.Y/2),(part.Size.Z/-2))
				local rightEdge2 = topSurface * CFrame.new((part.Size.X/2),(part.Size.Y/2),(part.Size.Z/2))

				-- distance between corner and player
				local distanceFromleftEdge1 = (leftEdge1.Position - self.Char.HumanoidRootPart.CFrame.Position).Magnitude
				local distanceFromleftEdge2 = (leftEdge2.Position - self.Char.HumanoidRootPart.CFrame.Position).Magnitude
				local distanceFromrightEdge1 = (rightEdge1.Position - self.Char.HumanoidRootPart.CFrame.Position).Magnitude
				local distanceFromrightEdge2 = (rightEdge2.Position - self.Char.HumanoidRootPart.CFrame.Position).Magnitude

				edges[1] = {distanceFromleftEdge1,leftEdge1}
				edges[2] = {distanceFromleftEdge2,leftEdge2}
				edges[3] = {distanceFromrightEdge1,rightEdge1}
				edges[4] = {distanceFromrightEdge2,rightEdge2}

				print(edges)

				table.sort(edges, function(a,b) -- sort by distance. smallest first and biggest last.
					return a[1] < b[1]
				end)

				local edge1 = edges[1]
				local edge2 = edges[2]


				local distanceBettweenCorners = (edge2[2].Position - edge1[2].Position).Magnitude -- making the edge from two corners

				local inBettween = edge1[2]:Lerp(edge2[2], (edge1[1]/distanceBettweenCorners)) -- getting the player distance and putting the player on the edge

				self.Char.PrimaryPart.CFrame = inBettween -- putting the player on the edge
			end

I’m trying to figure out how to get the exact face of a part the player is facing. Any assistance would be greatly appreciated.

I don’t know much about raycasting, but assuming the part is a block then all 6 faces have their own normal, can’t you just map those normals to faces?

1 Like

I don’t really know how you would do that, would you mind explaining it to me?

Getting the corners of a face is a bit more messy since you would need to know which Axis to use maths on, i’m lazy so i don’t know any easy way but i would just code 6 different axis calculations to get the corner of any face.

this is the image i always refer to whenever i need to get the corners of a basepart.

https://images-ext-2.discordapp.net/external/2GsFJHd-N6zdLu0BdOWjj4B7KZBhhIQ3TtO0vyE4JIo/%3Fwidth%3D1009%26height%3D676/https/media.discordapp.net/attachments/932657144191414303/941875705925476402/6b6f081efba33170e35eb80346909228.png

EDIT:
don’t exactly understand the intention of the OPs code, from what it seems you want it so the player can only climb the corners of an instance

3 Likes
local function GetEnumNormalFromRay(ray :RaycastResult)	
	local part = ray.Instance
	local Position = ray.Position	

	local Normal = {
		[1] = {Position = part.CFrame * CFrame.new(0,0,-part.Size.Z/2),EnumNormal = Enum.NormalId.Front},
		[2] = {Position = part.CFrame * CFrame.new(0,part.Size.Y/2,0),EnumNormal = Enum.NormalId.Back},
		[3] = {Position = part.CFrame * CFrame.new(0,part.Size.Y/2,0),EnumNormal = Enum.NormalId.Top},
		[4] = {Position = part.CFrame * CFrame.new(0,-part.Size.Y/2,0),EnumNormal = Enum.NormalId.Bottom},
		[5] = {Position = part.CFrame * CFrame.new(part.Size.X/2,0,0),EnumNormal = Enum.NormalId.Right},
		[6] = {Position = part.CFrame * CFrame.new(-part.Size.X/2,0,0),EnumNormal = Enum.NormalId.Left},
	}		

	local Closest = Normal[1]

	for _,Side in pairs(Normal) do
		Side.Position = Side.Position.Position
		local lookForward = Vector3.fromNormalId(Side.EnumNormal)
		local lookToPoint = (Side.Position - Position).unit

		local angle = math.deg(math.acos(math.clamp(lookForward:Dot(lookToPoint), -1, 1)))
		
		if (Side.Position - Position).magnitude < (Closest.Position - Position).magnitude then
			if angle < 90 then
				Closest = Side
			end
		end
	end

	return Closest.EnumNormal
end

local ray = workspace:Raycast(Vector3.new(1,10,0),Vector3.new(0,-15,0))

print(GetEnumNormalFromRay(ray))
3 Likes