Is there a way to get the surface inclination angle of a part surface?

Is there a way to get the surface inclination of a sphere?
Like doing a raycast that hits a sphere and get the inclination angle of the hit point surface?

2 Likes

Yes, it is possible to get the surface inclination of a sphere by doing a raycast and using the SurfaceNormal property of the RaycastHit object that is returned.

Here is an example of how you can do this in Roblox Lua:

local origin = Vector3.new(0, 0, 0) -- the starting point of the raycast
local direction = Vector3.new(0, 0, -1) -- the direction of the raycast
local range = 10 -- the maximum distance of the raycast
local sphere = game.Workspace.Sphere -- the sphere object to cast the ray on

-- Perform the raycast and get the hit object
local hit, position, normal = game.Workspace:Raycast(origin, direction, range)

-- If the raycast hits the sphere
if hit == sphere then
  -- Calculate the inclination angle
  local inclination = math.deg(math.acos(normal.Z))
  print(inclination) -- print the inclination angle
end

This code will perform a raycast from the origin point (0, 0, 0) in the direction (0, 0, -1) (straight down) with a maximum distance of 10 units. If the raycast hits the sphere object, it will calculate the inclination angle of the surface at the hit point and print it.

The inclination angle is calculated by using the acos function to get the angle between the surface normal and the Z axis (which is pointing upwards), and then converting it to degrees using the deg function. The normal vector is a unit vector that points in the direction of the surface normal at the hit point, so it has a length of 1 . The Z component of the normal vector is the projection of the normal vector onto the Z axis, and it ranges from -1 (downwards) to 1 (upwards). The acos function returns the angle in radians between 0 and π (180 degrees), so we need to use the deg function to convert it to degrees.

Keep in mind that this code is just an example and you will need to adjust it to fit your specific needs. You will need to specify the origin, direction, range, and sphere object appropriately in your own code

4 Likes

Thank you so much. It totally makes sense, thank you. But for some reason, Im getting normal = nil using this script, do you know what could be the reason?

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {script.Parent}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

local rayOrigin = script.Parent.Position
local rayDestination = game.Workspace.Sphere.Attachment.WorldPosition

local rayDirection = rayDestination - rayOrigin

while true do
	local hit, position, normal = game.Workspace:Raycast(rayOrigin, rayDirection, raycastParams)

	if hit then
		warn(hit.Instance) -- This is showing the sphere instance in output
		warn(normal) -- This is nil
		if normal then
			local inclination = math.deg(math.acos(normal.Z))
			print(inclination) -- print the inclination angle
		end

	end
	wait()	
end

There are a few things you can try to fix the issue:

  1. Make sure that the hit variable is not nil . If hit is nil , then the raycast did not hit anything, and normal will also be nil .
  2. Make sure that the object that the raycast hit has a surface with a normal vector. Some objects, such as parts with the “Smooth” material, do not have a surface normal vector.
  3. Make sure that the normal variable is being set correctly in the Raycast function. The Raycast function should return three values: a boolean value indicating whether the raycast hit something, a Vector3 value representing the position where the raycast hit, and a Vector3 value representing the normal vector at the point where the raycast hit. If the normal variable is not being set correctly, it could be because of an issue with the Raycast function itself.

Thats the reason then. Im using a simple part with ball shape. Then that part has not normals? Should be a sphere mesh?

If you are using a simple part with a sphere shape, and you want to use a raycast to get the normal vector at the point where it hits the object, you may need to use a different object or material. Alternatively, you could try adding a surface normal vector to the object manually, either by modeling the object with surface normals or by applying a normal map to the object.

I tried with a couple of sphere meshes from tool box, still not getting normals, I changed the part material of the simple ball part, still not getting normal result.
I know nothing about normal maps, I guess I should do a research

1 Like