How to Use Normal Vector to Align Part to Ramp

I’m not sure how to convert the normal vector into useful data. I’m ray casting downwards to determine where to place this block, but when placed on a ramp, it doesn’t align because I don’t know how to. I’m trying to align the block so that it adjusts to ramps. plz help D: me no math wizard

1 Like

What you could do is capture the part that the ray hits’s CFrame:

local ray =, direction)
local part, position = workspace:FindPartOnRay(ray)

if part then
     local yourNewPart = yourPart:Clone()
     -- Get the component parts of the part it hits CFrame
     local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22 = part.CFrame:GetComponents()     
     -- Set the cloned part's CFrame
     yourNewPart.CFrame =, position.Y, position.Z, r00, r01, r02, r10, r11, r12, r20, r21, r22)

This will align your part to the same orientation as the part it hits, while maintaining the position given!

Side note:
This only works if all the parts it will be hitting are orientated top-side up! So make sure that the top of all the parts point upwards. (You can check by creating a motor/hinge surface in Part properties)

1 Like

This doesn’t work in this case because this is a wedge part and the orientation is 0. I’m pretty sure the normal vector is going to need to be used in order for this to work.

In that case what you’re asking is some annoying math, you need to calculate out the angle of the wedge using trigonometry and figure out which way the wedge is pointing. This is an impractical application as if you were to encounter CSG Unions or MeshParts, the code will no longer work. (My code above also has that flaw) I’m not familiar with how wedges orient themselves, but you’re better off finding a different solution or using rotated parts. As wedges would require a lot of really unnecessary math.

The responses in this thread are incorrect. The surface normal is essentially a vector that points directly away from the surface.

One easy way of using this data is, part_pos + normal). This will cause the object to ‘look at’ the surface normal, thus “aligned” with it. You can simply rotate this CFrame to orient it in whichever way you want relative to the surface.

Refer to thread: Explanation of Surface Normal?


you can add a clone for an invisible pre-rotated part on the ramp.
and then when the item finds a ramp. it just takes that that pre rotated part’s cframe rotation to align, LookAt) is being depreciated, while CFrame.fromMatrix() is not, this method is a little more complicated, but is better than it’s relative, in fact even the Roblox definition of a CFrame says that the .fromMatrix() method is more accurate and stable.
An explanation of fromMatrix is found here:

heres a function to replace, LookAt)

local function CFrameLookAt(pos, look)

	 local lookvec = (pos - look).Unit 
	 local rightvec = lookvec:Cross(,1,0))
	 local upvec = rightvec:Cross(lookvec)

	return CFrame.fromMatrix(pos, rightvec, upvec)


Thank you for linking the tutorial. However, I do want to say that there is a new constructor called CFrame.lookAt() which works very similarly to the deprecated counterpart, but with the added flexibility of manipulating the up vector. So, I’d recommend this option in general and especially for beginners. I’m glad CFrame.fromMatrix() has a much nicer cousin.