Get NormalId From FindPartOnRay

Hey there!
I am trying to get the Enum.NormalId with FindPartOnRay its Normal. I found something that was made back in 2015 but that doesn’t work anymore.
anyone could write a quick function that I can return the NormalVector to and it returns the Enum or Number of the NormalId?

Script from 2015:
function n(v) return Enum.NormalId:GetEnumItems()[(-v.Y+3v.Y^2-v.Z+7v.Z^2-v.X+11*v.X^2)/2] end
My output:
image

FindPartOnRay returns a few things

The BasePart (or Terrain) hit, the Vector3 point of intersection, the Vector3 surface normal at the point of intersection and the Material of the BasePart or terrain cell hit.

Now what you can do is have a table like:

local Normals = {
[Vector3.new(0,1,0)] = Enum.NormalId.Top
}

then get the Normal returned from the Ray and check if it exists in the dictionary (obviously if it does you’ll get the Enum you want)

1 Like

Because Vector3s are unique userdata values, a table lookup won’t work.

@DutchDeveloper You’ll have to resolve this with a function, obviously. You have a choice between hardcoding vectors in an elseif tree or somehow procedurally determining what NormalId it’s facing. I would personally go for the hardcoded variant because it’s easier to read. I got the NormalVectors for each NormalId using Vector3.FromNormalId.

local function normalIdFromVector(vector)
    if vector == Vector3.new(0, 1, 0) then
        return Enum.NormalId.Top
    elseif vector == Vector3.new(0, -1, 0) then
        return Enum.NormalId.Bottom
    elseif vector == Vector3.new(0, 0, 1) then
        return Enum.NormalId.Back
    elseif vector == Vector3.new(0, 0, -1) then
        return Enum.NormalId.Front
    elseif vector == Vector3.new(1, 0, 0) then
        return Enum.NormalId.Right
    elseif vector == Vector3.new(-1, 0, 0) then
        return Enum.NormalId.Left
    end
end
4 Likes

The issue appears to be floating point error. The standard way to remedy such errors is to use some wiggle room… if the dot product is less than 0.01 off, the following function will return the relevant NormalId:

local function normalIdFromVector(vector)
    local epsilon = 0.01
    for _, normalId in pairs(Enum.NormalId:GetEnumItems()) do
        if vector.unit:Dot(Vector3.FromNormalId(normalId)) > 1 - epsilon then
            return normalId
        end
    end
end
9 Likes