How to get the best normal

if my character was under some blocks, how would i try to get the best normal? its obvious that the normal should be (0, -1, 0) but im having a hard time trying to solve this.

normal results:

code:

local rig = workspace.Rig
local rootPart = rig.HumanoidRootPart

local lastNormal = vector.zero
local searchSize = vector.create(2, 5, 2)

local visualizer = Instance.new("Part")
visualizer.Name = "Visualizer"
visualizer.Anchored = true
visualizer.CastShadow = false
visualizer.CanCollide = false
visualizer.CanQuery = false
visualizer.Color = Color3.fromRGB(255, 0, 0)
visualizer.Transparency = .5
visualizer.Size = searchSize
visualizer.Parent = workspace

local overlapParams = OverlapParams.new()
overlapParams.ExcludeInstances = {rig}

local function calculateNormal(part1: BasePart, part2: BasePart): vector
	local pos = rootPart.Position
	local size = rootPart.Size
	
	local hitPos = part2.Position
	local hitSize = part2.Size
	
	local halfX = (hitSize.X + size.X) * .5
	local halfY = (hitSize.Y + size.Y) * .5
	local halfZ = (hitSize.Z + size.Z) * .5

	local difference = hitPos - pos

	local overlapX = halfX - math.abs(difference.X)
	local overlapY = halfY - math.abs(difference.Y)
	local overlapZ = halfZ - math.abs(difference.Z)
	
	local minOverlap = math.min(overlapX, overlapY, overlapZ)

	local normal = vector.zero
	
	if minOverlap == overlapX then
		normal = vector.create(-math.sign(difference.X), 0, 0)
		
	elseif minOverlap == overlapY then
		normal = vector.create(0, -math.sign(difference.Y), 0)
	else
		normal = vector.create(0, 0, -math.sign(difference.Z))
	end
	
	return normal
end

while task.wait(.5) do
	local origin = rootPart.Position
	local size = rootPart.Size
	local cframe = rootPart.CFrame + vector.create(0, searchSize.y * .5, 0)
	local parts = workspace:GetPartBoundsInBox(cframe, searchSize, overlapParams)
	
	visualizer.Position = origin
	
	local totalNormal = vector.zero
	
	for _, part in parts do
		local normal = calculateNormal(rootPart, part)
		totalNormal += normal
		print(normal)
	end
	
	print("----------------")
end

place file:
normal.rbxl (71.1 KB)

1 Like

You can get the average position (center) of all the body parts completely encased by the blocks, let’s call it CoveredCenter, and the center of the entire character model, BodyCenter, and subtract the two while indexing Unit to get a unit direction.

local UnitDirection = (CoveredCenter - BodyCenter).Unit

Let’s say UnitDirection = (0.04, -0.78, -0.21), all you have to do is match it with the closest normal axis, in this case it would be (0, -1, 0).

1 Like

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