Any way to tell if a position is on a certain face of an object?

So I am currently creating a system, something that would help with it is being able to tell if a position is on a certain face of a part.

For instance, the faces I mean are like the front face, back, left, right, bottom, top.
Uh yeah. Thanks!

2 Likes

You’re going to want to get the pos of ur part and ur point and make a vector between the two. Next you’re going to want to see which direction it’s going through. If it’s going more up then it is ur top surface. BUT your part could be rotated. So you must take that into account too. You can ask ChatGPT on specifics for code as I’ve given a very broad explanation.

Because this will take some vector math

2 Likes

i think you can use Enum.NormalId

But how would I get the face the position is on, not all faces?

Do you have any idea on where I’d begin with doing this taking account for the orientation of the object?

Other than that thanks!

An alternative solution that might be a tad bit easier could be using raycasting, RaycastResult objects do have a normal field that indicates the surface of the part that was hit.

You could do something like turning that point into a CFrame and then extending it outwards, cast a ray from that point to the part to find the normal it struck.

1 Like

No lie I have no clue😭. But after rethinking and doing sum research here’s why I got

function getFace(part, point)
    -- Convert the point to local space relative to the part
    local localPoint = part.CFrame:PointToObjectSpace(point)

    -- Get the size of the part (half-size for boundary checks)
    local halfSize = part.Size / 2

    -- Check which face the point is closest to
    if math.abs(localPoint.X - halfSize.X) < 0.001 then
        return Enum.NormalId.Right
    elseif math.abs(localPoint.X + halfSize.X) < 0.001 then
        return Enum.NormalId.Left
    elseif math.abs(localPoint.Y - halfSize.Y) < 0.001 then
        return Enum.NormalId.Top
    elseif math.abs(localPoint.Y + halfSize.Y) < 0.001 then
        return Enum.NormalId.Bottom
    elseif math.abs(localPoint.Z - halfSize.Z) < 0.001 then
        return Enum.NormalId.Back
    elseif math.abs(localPoint.Z + halfSize.Z) < 0.001 then
        return Enum.NormalId.Front
    else
        return nil -- Point is not exactly on a face
    end
end

-- Example Usage
local part = workspace.Part -- Replace with your part
local point = Vector3.new(5, 10, 15) -- Replace with your point

local face = getFace(part, point)
if face then
    print("The point is on the", face.Name, "face")
else
    print("The point is not on a face")
end

After rethinking w some help here what I got :money_mouth_face:

Note: I used ChatGPT for this lol sooo u should too before coming on here. I personally use it for complex ideas or ones I’m too dumb to solve. Plus answers are wayy more faster!

1 Like

Hello! So I modified the code some cause I would also like to check the face without it being relative too the part. I tried just doing this:

--[[
Returns the Face the @Point is on, on the @Part.

Face = Enum.NormalId
]]
function getFace(part:BasePart, point:Vector3, locally:boolean)
	-- Convert the point to local space relative to the part
	local localPoint = point; if locally then localPoint = part.CFrame:PointToObjectSpace(point) end

	-- Get the size of the part (half-size for boundary checks)
	local halfSize = part.Size / 2

	-- Check which face the point is closest to
	if math.abs(localPoint.X - halfSize.X) < 0.001 then
		return Enum.NormalId.Right
	elseif math.abs(localPoint.X + halfSize.X) < 0.001 then
		return Enum.NormalId.Left
	elseif math.abs(localPoint.Y - halfSize.Y) < 0.001 then
		return Enum.NormalId.Top
	elseif math.abs(localPoint.Y + halfSize.Y) < 0.001 then
		return Enum.NormalId.Bottom
	elseif math.abs(localPoint.Z - halfSize.Z) < 0.001 then
		return Enum.NormalId.Back
	elseif math.abs(localPoint.Z + halfSize.Z) < 0.001 then
		return Enum.NormalId.Front
	else
		return nil -- Point is not exactly on a face
	end
end

The only problem is that it only works with the top and bottom now, Im really bad with all these positions and their maths so if you have any idea what the issue is that’d be great lol.

--[[
Returns the Face the @Point is on, on the @Part.

Face = Enum.NormalId
]]
function getFace(part: BasePart, point: Vector3, locally: boolean)
    local localPoint

    if locally then
        -- Convert point to local space
        localPoint = part.CFrame:PointToObjectSpace(point)
    else
        -- Use world space directly
        localPoint = point - part.Position
        localPoint = part.CFrame:VectorToObjectSpace(localPoint)
    end

    -- Get the size of the part (half-size for boundary checks)
    local halfSize = part.Size / 2

    -- Check which face the point is closest to
    if math.abs(localPoint.X - halfSize.X) < 0.001 then
        return Enum.NormalId.Right
    elseif math.abs(localPoint.X + halfSize.X) < 0.001 then
        return Enum.NormalId.Left
    elseif math.abs(localPoint.Y - halfSize.Y) < 0.001 then
        return Enum.NormalId.Top
    elseif math.abs(localPoint.Y + halfSize.Y) < 0.001 then
        return Enum.NormalId.Bottom
    elseif math.abs(localPoint.Z - halfSize.Z) < 0.001 then
        return Enum.NormalId.Back
    elseif math.abs(localPoint.Z + halfSize.Z) < 0.001 then
        return Enum.NormalId.Front
    else
        return nil -- Point is not exactly on a face
    end
end

-- Example Usage
local part = workspace.Part -- Replace with your part
local point = Vector3.new(5, 10, 15) -- Replace with your point

local face = getFace(part, point, false) -- `false` = world space
if face then
    print("The point is on the", face.Name, "face")
else
    print("The point is not on a face")
end
1 Like

hmm for whatever reason it appears to always return nil now, any ideas as too why? Even if its relative or not it still returns nil from the look of it.

Perhaps change the 0.001 to to something bigger

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