Detecting if player is on something properly

So basically i’m trying to make an inertia type script but it’s just so hard to detect if the player is airborne or not, because raycast doesn’t detect meshes and floormaterial is just not good.

Anyone know any fix to that?

local Root = script.Parent:WaitForChild("HumanoidRootPart") :: Part
local Attachment = script:WaitForChild("Attachment")
local LinearVelocity = script:WaitForChild("LinearVelocity")
local RunService = game:GetService("RunService")

local Humanoid = script.Parent:FindFirstChild("Humanoid")

local lastPosition = Root.Position
local velocity = Vector3.new(0,0,0)

Attachment.Parent = Root
LinearVelocity.Parent = Root

local X = 0
local Z = 0

RunService.Heartbeat:Connect(function(deltaTime)
	velocity = (Root.Position - lastPosition) / deltaTime
	lastPosition = Root.Position
	
	if X < velocity.X then
		X += (velocity.X - X) * 0.1
	elseif X > velocity.X then
		X += (velocity.X - X) * 0.025
	end
	
	if Z < velocity.Z then
		Z += (velocity.Z - Z) * 0.1
	elseif Z > velocity.Z then
		Z += (velocity.Z - Z) * 0.025
	end
	
	if Humanoid.FloorMaterial == Enum.Material.Air then -- detect if player airborne or not
		LinearVelocity.VectorVelocity = Vector3.new(X, 0, Z)
		LinearVelocity.MaxAxesForce = Vector3.new(9000, 0, 9000)
	else
		LinearVelocity.VectorVelocity = Vector3.zero
		LinearVelocity.MaxAxesForce = Vector3.zero
	end
end)
2 Likes

What do you mean by raycasting not detecting meshes? Are you using a proper collision fidelity on your models?

Which collision fidelity is considered proper?

PreciseConvexDecomposition, meshes usually default to box instead.

If you’re using bones or mesh deformation, raycasting inaccuracies are pretty much impossible to fix as the rendered mesh is different from the computed mesh behind the scenes. Try updating the CollisionFidelity first though.

--LocalScript in StarterPlayerScripts
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

RunService.RenderStepped:Connect(function()
	if Humanoid:GetState() == Enum.HumanoidStateType.Freefall then
		-- Player is in freefall
	end

	if Humanoid.FloorMaterial == Enum.Material.Air then
		-- Player is airborne
	end
end)

Actually don’t like to use loops like this.. I tend to sick with event driven approaches.
This stuff just screams AI bail out approach, constantly usings loops like this.

This is literally an event connected function though? No loops here

I really don’t like them loops. I was following his script to show a possible way to check this..
I’d rather use:

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

That is event driven.. no loop.

Yeah so, I presume you don’t have a clue what you’re talking about. There’s no loop happening there. Just a function being called per frame. And for their case, unless there’s a humanoidStateChanged event which I can’t remember and am too lazy to search up, using per frame detection is perfectly valid and most of the times the only reliable way unless roblox prepared some hand-helding helper event.

so you’re telling me you don’t think this is a non-stop loop.. I said I’m not a fan of these loops. That doesn’t mean I didn’t go with it and post a fix using that loop set up.

Forgive me if I’m mistaken, but doesn’t roblox have a builtin way of detecting if a player is in the air? I think it’s called HumanoidStateType (link to the roblox documentation here). You could use the “Freefall” and “Jumping” HumanoidStateTypes to detect if the player is airborne.

Example:

if Humanoid:GetState() == Enum.HumanoidStateType.Jumping or Humanoid:GetState() == Enum.HumanoidStateType.Freefall then
    --Add what will happen when the player is airborne
end
1 Like

Player is in the air .. try it

--LocalScript in StarterPlayerScripts
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")

while true do
	print(hum.FloorMaterial.Name)
	task.wait()
end

Simple print test to show what this is reading in real time. When you jump it’s going to print air.

are you using a part with a mesh instance, or are you using a meshpart…? raycast should detect meshparts just fine

Exactly :slight_smile: a loop is a loop. Which means variations of the while loop (such as for or repeat). A function that’s running on game frames is by no definition a loop.

Did you understand what he meant by “loop”? If you did, then there should be no problem. If you didn’t, I would suggest you work on improving your cognitive abilities :slight_smile:. What he means is that he would prefer to use event-driven logic that relies on signals to detect changes in a property rather than repeatedly and continuously running checks, AKA a loop. While by definition, you are correct,

a series of instructions (as for a computer) that is repeated until a terminating condition is reached

the difference between a loop and an event that continuously fires is minimal. Also, said condition can be thought of as permanently true, as it is in a while true loop.

1 Like

Could try using a ControllerPartSensor, that’s what I’m using rn for detecting if the player is on something, and what the instance is
https://create.roblox.com/docs/reference/engine/classes/ControllerPartSensor

1 Like

A traditional loop is a loop and so is a frame loop.. and that is what this is..

RunService.Heartbeat:Connect(function()

It repeats every frame, but it is event-driven, not a blocking loop.
I’ll bet you my master’s degree this is right… You can stop PMing me ranting too.

“you can stop pming me” my guy messaged me first asking for an apology cuz he felt hurt, and now he’s acting all nonchalant when he got a response lol. Also flexing masters degree on roblox forum? Crazy stuff lol. Use a proper wording next time and don’t be mad over corrections :face_blowing_a_kiss:

I guess it really depends on the take, the difference between a continuous loop and a frame bound function is quite big. I presume it’s not as much so when you’re solely focusing on roblox scripting, but practically, they’re very different.

I said you should not talk to kids that way (from a totally different post) and should apologize. No one felt hurt, get over yourself. You don’t know what you’re talking about and too toxic to let it go. Who cares. Did you have to look up frame loop? The outcome is the same.. It’s a nonstop loop for no reason in this case. Go touch some grass.

1 Like