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
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.
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
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)