How to prevent players' feet from penetrating the ground?

hello

so i’m making a flight mode for the player character but when i fly down or you could say towards the ground hoping his feet don’t pierce the ground and the flight mode turns off, i’ve tried turning it off when it touches a horizontal object only if his feet touch a vertical object like a wall the flight mode won’t turn off, all suggestions are welcome

heres the function i made to detect the ground with player legs :

-- Function to check if the player is touching the ground while airwalking
function checkGroundTouch()
	local leftLeg = character:FindFirstChild("Left Leg") 
	local rightLeg = character:FindFirstChild("Right Leg") 

	if not leftLeg or not rightLeg then
		return
	end

	-- Function to handle the ground touch logic using legs
	local function handleGroundTouch(hit)
		if airwalking and hit.CanCollide then
			-- Get the normal of the surface
			local normal = hit.CFrame:VectorToWorldSpace(Vector3.new(0, 1, 0))

			-- Calculate the vertical threshold
			local verticalThreshold = 0.7 -- Adjust this threshold as needed

			-- Check if the hit surface is mostly vertical or horizontal
			if normal.Y < verticalThreshold then
				-- It's a horizontal surface
				local isGround = (hit:IsA("Part") and (hit.Material == Enum.Material.Grass or hit.Material == Enum.Material.SmoothPlastic))

				if isGround then
					print("Ending airwalk: Touched Ground.") 
					airwalkEnd() 
				end
			else
				print("Touched vertical surface: Continuing airwalk.")
			end
		end
	end

	-- Function to continuously check for ground contact while flying
	local function checkGroundBelow()
		while airwalking do
			wait(0.1)
			local rayOrigin = leftLeg.Position
			local rayDirection = Vector3.new(0, -1, 0) * 10 -- Length of the raycast
			local ray = Ray.new(rayOrigin, rayDirection)

			local hit, position = workspace:FindPartOnRay(ray, character)

			if hit and hit.CanCollide then
				local isGround = (hit:IsA("Part") and (hit.Material == Enum.Material.Grass or hit.Material == Enum.Material.SmoothPlastic))
				if isGround then
					print("Ending airwalk: Touched Ground from raycast.")
					airwalkEnd() 
					break 
				end
			end
		end
	end

	leftLeg.Touched:Connect(handleGroundTouch)
	rightLeg.Touched:Connect(handleGroundTouch)

	checkGroundBelow()
end

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		checkGroundTouch(character) 
	end)
end)

for _, player in pairs(Players:GetPlayers()) do
	if player.Character then
		checkGroundTouch(player.Character)
	end
end

here the problem ive been facing

robloxapp-20241023-0453540.wmv (2.8 MB)

But you’re only calling the checkGroundTouch function one time when the player is added. The loops inside the function never run because when they’re added airwalking is false.

Instead of adding the function at the beginning just use a single Touched function that does it instead in a loop that only runs while the player is flying. Have the first check in the function see if the item touched is a ground part (you can do this with Tags or Attributes) and if it is.

A better alternative would be just to fire a short ray straight down from the player and if the ray sees a surface then stop the flying. No Touched event needed.

1 Like

im sorry im still learning raycasting can you show me how to do it?

i mean i can do it with touched function which of course it will stop without penetrating to the ground but when the leg touch like vertical object like wall it will stop too so it not very effective to to use touched