How would i use the surface normal to get the edge of a part?

I need some help detecting a parts edge and I am raycasting from the Camera’s position I want to make something along the lines of this short video


This doesn’t looks something easy to do, ngl, it would take a lot of code, but, you’re trying to make something like a ‘rappel’ thingy? or similar?

1 Like

From eyeing the GIF, I think the best way to replicate it is to:

  1. Get the position of the raycast hit on that building from the camera
  2. Set the Y position of that raycast hit to the building’s position + its Y size divided by 2
  3. Draw visual effect at that location.
local part, pos = workspace:Raycast() -- this is example, parameters are excluded
pos =, part.Position.Y + part.Size.Y, pos.Z)
-- draw visual at pos

The main limitation is that the buildings cannot have an X or Z CFrame axis rotation. (Its rotation value in properties must be 0, N, 0 where N is any number). In addition, the buildings cannot have its roof be made of spheres, wedges, or composite shapes. I think it should be the fastest approach to do if you’re willing to accept the limitations.


How would i use the surface normal to get the edge of a part?

The surface normal is a “direction” vector that points away from the surface that the raycast hit, so it’s not useful.

Your solution is good (other than part.Position.Y + part.Size.Y, which should be part.Position.Y + part.Size.Y / 2). Here’s how to get rid of that limitation.

You assume that the part is upright, i.e. the top surface of the part points to the sky, i.e. the normal of the top surface is (0, 1, 0), so you move the position in that direction.
But you can get the “top” direction of a part from its CFrame — it’s part.CFrame.UpVector. If pos is a point on the part, then pos + part.CFrame.UpVector * 5 is the same point moved 5 studs toward the TopSurface of the part, regardless of the part’s rotation. (The point can be moved downward if the part is upside down, or sideways if the part is resting on its side.)

You don’t know how close the part is to the top, though, so you don’t know what to change that 5 to. Here’s how to learn it.
The dot product of two vectors can tell you how far in one of the vectors’ direction the other is. Here is an example:

> print(, 0, 0):Dot(, 0, 0)))
> print(, 0, 0):Dot(, 0, 0)))
> print(, 0, 0):Dot(, 652468756, -789878754231)))
> print(, 1, 1).unit:Dot(, 652468756, -789878754231)))

Note that the “directions” must be relative to the same point.
To know how far from the vertical middle of the part pos is, you’d do something like this:

-- found earlier
local part, pos

-- since part.CFrame.UpVector is relative to the part's position, we need pos to be relative to part's position too, to get a useful result
local pos2 = pos - part.Position 

-- if pos were at the vertical middle of the face that was hit, this would be 0. if it were at the top, this would be part.Size.Y/2. if it were at the bottom, this would be -(part.Size.Y/2)
local distance = part.CFrame.UpVector:Dot(pos2)

-- how much we need to move to reach the top edge
local distanceLeft = part.Size.Y/2 - distance

-- our point, adjusted
pos = pos + part.CFrame.UpVector * distanceLeft

But if I were to make the system in the GIF, I’d rather mark the edges that can be targeted manually.
This is because the building in the GIF is complex and decorated, and trying to do the above to whatever your ray hits would result in finding the top edge of a small brick in the wall, which isn’t appropriate.
I’d place parts over the edges that are visible in the editor, but are processed and turned invisible when the game starts. These parts should be targetable by raycast or by mouse.Target, and somehow resolve to an “edge” that can be grappled.


Thank you so much it actually worked ive been trying all day yesterday, could you give me an explanation of how it’s working im not very good at math and dont understand it that well

Thank you ill give that a og if Im having any troubles with the method @treebee63 gave me, thank you both for the help saved me asp