Raycast fail because origin inside target surface

I’m currently making a small destruction script which i will use in a future game and in order to prevent some glitch(Breaking while moving across a flat surface) in need to get the touched surface normal of the touched part.

In the code, i use raycast to get the surface normal of the touched part(The final version will use vertice data). The problem comes from Roblox physic being wobbly which make the part(In this case the character limbs) go trough the touched part for some micro second. Then while the part is inside, the game raycast in the center of the hited part but it fails because the raycast origin is inside of hitted part and then when it reach the center it considers not hitting any surface so it errors.

The first version of the script used math to detect which side was the part position from the center Ex : If you are on top it will return 0,1,0 as normal and that for every side. But again, there was a problem which made it not function properly and return 75% of the time 0,0,1 or 1,0,0 as a normal when you where on top of something(0,1,0)

Here is the simplified version of the code. Just put it inside and r15 character(What im testing it on) and watch the script show the error when he fall or get hitted hard.

local Childrens = script.Parent:GetChildren()
local MinForce = 25

for i, v in pairs(Childrens) do
	if v:IsA("PVInstance") and not v:IsA("Model") and v.Name ~= "HumanoidRootPart" then
		v.Touched:Connect(function(Hit)
			if Hit.Parent ~= v.Parent then
				local AppliedForce = Vector3.new(math.abs(Hit.AssemblyLinearVelocity.X - v.AssemblyLinearVelocity.X), math.abs(Hit.AssemblyLinearVelocity.Y - v.AssemblyLinearVelocity.Y), math.abs(Hit.AssemblyLinearVelocity.Z - v.AssemblyLinearVelocity.Z))
				if AppliedForce.X >= MinForce or AppliedForce.Y >= MinForce or AppliedForce.Z >= MinForce then
					local RayDirection = (Hit.Position - v.Position)

					local raycastParams = RaycastParams.new()
					raycastParams.FilterDescendantsInstances = {Hit}
					raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
					local raycastResult = workspace:Raycast(v.Position, RayDirection, raycastParams)

					VisualiseRaycast(v.Position, RayDirection, raycastResult, v)

					if raycastResult then
						print(raycastResult.Normal)
					end
				end
			end
		end)
	end
end

function VisualiseRaycast(Origine, Direction, Result, Caster)
	local Visualiser = Instance.new("Part", workspace)
	local FinalPos = Origine + Direction
	local Distance = (Origine - FinalPos).Magnitude
	
	Visualiser.Anchored = true
	Visualiser.CanCollide = false
	Visualiser.CanTouch = false
	Visualiser.Size = Vector3.new(0.1, 0.1, Distance)
	Visualiser.CFrame = CFrame.lookAt(Origine, FinalPos) * CFrame.new(0, 0, -Distance / 2)

	if Result then
		Visualiser.Color = Color3.fromRGB(0, 255, 127)
		Visualiser.Name = "Succes"
	else
		local FailIndicator = Instance.new("Part", workspace)
		
		FailIndicator.Anchored = true
		FailIndicator.CanCollide = false
		FailIndicator.CanTouch = false
		FailIndicator.Name = Caster.Name
		FailIndicator.Position = Caster.Position
		FailIndicator.Size = Caster.Size
		
		Visualiser.Color = Color3.fromRGB(170, 0, 0)
		Visualiser.Name = "Failed"
		
		warn("Raycast Failed")
	end
end