# 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

2 Likes

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 = Vector3.new(pos.X, 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.

4 Likes

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.

@treebee63
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(Vector3.new(1, 0, 0):Dot(Vector3.new(1, 0, 0)))
1
> print(Vector3.new(1, 0, 0):Dot(Vector3.new(0.5, 0, 0)))
0.5
> print(Vector3.new(1, 0, 0):Dot(Vector3.new(10, 652468756, -789878754231)))
10
> print(Vector3.new(1, 1, 1).unit:Dot(Vector3.new(10, 652468756, -789878754231)))
-455659978752
``````

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