Detect if player is touching terrain

hello, i have this script that i only want to run if a player is on terrain, how would I detect if the player is on terrain?

Raycast below the player’s torso to determine if they are standing on terrain.

I believe you can get the Floor Material by Humanoid.FloorMaterial

You can use Character.Humanoid.FloorMaterial if you want to check if they’re standing on a specifc material. hope it helps.

Its not material, its terrain.

You may be able to do FloorMaterial:IsA()

So you mean like this

if Humanoid.FloorMaterial:IsA("Terrain") then
				
			end
1 Like

How would i use raycast for this?

Raycast a ray facing downwards and detect if raycast is hitting terrain?

Unsure if that was a sarcastic question, as I’m unsure if raycasts detect terrain

Well, i actually though if another idea and this idea has to start by detection if a player is in the air or not using an if statement

if Humanoid.State == Enum.HumanoidStateType.Freefall then

but for some reason it wont work

The method is raycast downwards from the rootpart every frame. The ray length has to be short enough to barely touch the ground. Doing so will prevent the ray from hitting the ground when the player jumps or in the air.

local rayCastGroundCheck = workspace:Raycast(rootPart.Position, -rootPart.CFrame.UpVector * (hipHeight + 0.5), RayParams)

The ray result will return “nil” if it hits nothing so do a if-else to check. If the ray hits something, check the instance if it :isA"Terrain"

You can try reading up on raycasting. The roblox documentation has more information,

Hope this helps.

Can we go to my new idea? Im think that could be more efficient for what i want

targetPlayerHumanoid.StateChanged:Connect(function(old, new)
	if (new == Enum.HumanoidStateType.Jumping) or (new == Enum.HumanoidStateType.Freefalling) then
local connection 

local function checkTerrain()
local rp = targetPlayer:WaitForChild("HumanoidRootPart")
local rayOrigin = rp :GetPivot().p
local rayDirection = rp.CFrame.UpVector*-20

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {targetPlayer}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.IgnoreWater = false

local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

if raycastResult then

local hitpart = raycastResult.Instance
if hit.part:IsA("Terrain") then 
print("Found terrain")
connection:Disconnect()
end

	connection = game:GetService("RunService").Heartbeat:connect(checkTerrain)
	end
end)

unsure if this will work, i have not tested it.

Well, wont this fire if the players humanoid statetype is changed, which i dont want. Also i asked if we could move the the other idea

Just raycast downwards every frame without disconnecting from the frame and conditions (i.e. without Humanoid.StateChanged).

With the

  • rayOrigin = rootPart.position
  • rayDirection = -rootPart.CFrame.UpVector * (hipHeight + 0.5)
  • raycastParams.FilterDescendantsInstances = {char}

You can find the hipHeight by doing some simple calculation,
https://create.roblox.com/docs/reference/engine/classes/Humanoid#HipHeight

The ray’s length is very important (+0.5 seems to be good enough) to not detect ground when the player jumps or is in the air. You will know every frame if the player is touching a terrian

Btw, this is same method used for custom vechicle to detect different surfaces on the ground.

1 Like

RS.RenderStepped:Connect(function(dt)
if Character.Humanoid.FloorMaterial == Enum.Material.Air then

		local targetVel = (Vector3.new(HRP.CFrame.LookVector.X*50, 0, HRP.CFrame.LookVector.Z*50) + HRP.Position).Unit * workspace.Gravity
		print(targetVel)
		local acceleration = targetVel - HRP.Velocity
		print(acceleration)
		BodyVelocity.Force = 10.8 * acceleration
	end
end)

This is what I did, change Humanoid.FloorType == Enum.Material.Air
To
Humanoid.FloorType ~= Enum.MaterialAir

1 Like

Step on lava you die … This is a local script in StarterGui named Signals. This is a snip from one thing that will happen. This scripts actually has many triggers depending on what they stepped on.

local rs = game:GetService("RunService")
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")

humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
	rs.Stepped:Wait()
	
-- snip
	if (humanoid.FloorMaterial) == Enum.Material.CrackedLava then
		humanoid.Health = 0
	end
end)