Detect when player falls from a tall height

I’ve made a Ragdoll Script which ragdolls the player while falling from a high place, but there’s one problem.

When the player spam jumps while walking, it ragdolls the player thinking they’re falling, same with small heights.

local player = game.Players.LocalPlayer
local char = script.Parent
local hum = script.Parent:WaitForChild("Humanoid")
local ragdolled = char:WaitForChild('Ragdolled')

local replicatedStorage = game:GetService("ReplicatedStorage")


hum.StateChanged:Connect(function(OldState, NewState)
	if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
		
		task.wait(0.5)
		if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
			replicatedStorage.RagdollServer:FireServer(char)
		end
		
	elseif hum:GetState() ~= Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
		wait(5)
		if hum:GetState() == Enum.HumanoidStateType.Physics then
			replicatedStorage.GetUp:FireServer(char)
		end
	end

	
end)

local function change_state()
	if ragdolled.Value then
		hum:ChangeState(Enum.HumanoidStateType.Physics)
	else
		hum:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end

ragdolled.Changed:Connect(change_state)

5 Likes

Are you using the Humanoid’s y velocity to detect when you fall from a high height or just the free falling state?

Free falling state, how does the velocity work? I’m new to scripting

you there? I tried body velocity but all it did was float the character

No you misunderstood.
If you checking your script closely, you will see that you’re making player ragdoll after they landed if they don’t land after 0.5 seconds. Meaning just by normal jump it might takes more than just 0.5 second to land which cause this issue.
So what @UwUanimsyt meaning is you should calculate the height from position player landed to position player jumped off if the height is more than , for example, 10 studs they will ragdoll.
(Also that BodyVelocity you’re using is for pushing, making force for object)

3 Likes

You can try something like this:

local maxFallTime = 5
local noDamage = 0.75
local human = player.Character:FindFirstChild("Humanoid")
local fallingTime = {}

human.StateChanged:Connect(function(old, new)
	local ident = player.UserId
	if new == Enum.HumanoidStateType.Freefall then
		fallingTime[ident].start = os.clock()
	elseif old == Enum.HumanoidStateType.Freefall then
		fallingTime[ident].stop = os.clock()
		local fallTime = (fallingTime[ident].stop - fallingTime[ident.start]) - noDamage
		if fallTime >= maxFallTime then
			human:TakeDamage(human.MaxHealth)
		elseif fallTime > 0 then
			human:TakeDamage(math.round((fallTime / maxFallTime) * human.MaxHealth))
		end
	end
end)

This does a few things, but basically, it checks the falling time and damages the player based on how long they fell.

  1. Check if the new humanoid state is freefall. If it is, then it saves the current time using os.clock() which is high precision.
  2. If the old state is freefall, then it save the current time again using os.clock(). Afterwards, it does a comparison between the two times (minus the dead time for no damage) to determine how much damage the humanoid should take. If the time is beyond the max fall time, then the humanoid is just outright killed. If the falling time is negative, which can happen if the falling time is less than the noDamage constraint, then no damage is done to the humanoid.

How would you check it mid air and run something when it detects you falling from high?

I tried this but it doesn’t work

local player = game.Players.LocalPlayer
local char = script.Parent
local hum = script.Parent:WaitForChild("Humanoid")
local ragdolled = char:WaitForChild('Ragdolled')

local replicatedStorage = game:GetService("ReplicatedStorage")


hum.StateChanged:Connect(function(OldState, NewState)
	if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
		
		local humHeight = char:WaitForChild("HumanoidRootPart").Position.Y
		
		repeat task.wait() until humHeight <= humHeight - 9
		replicatedStorage.RagdollServer:FireServer(char)
		
	elseif hum:GetState() ~= Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
		wait(5)
		if hum:GetState() == Enum.HumanoidStateType.Physics then
			replicatedStorage.GetUp:FireServer(char)
			script.PlayAnimation:FireServer()
		end
	end

	
end)

The problem is that you are using a Humanoid:StateChanged event, but you are not using the states that it’s giving you. The humanoid can be in only one state at a time. So the line

if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then

is pointless. Try the following code.

local playerService = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")

-- Get the player's critical parts.
local player = playerService.LocalPlayer
local char = player.Character
while char == nil do
	task.wait()
	char = player.Character
end
local hum = char:WaitForChild("Humanoid")
local root = char:WaitForChild("HumanoidRootPart")

local ragdolled = char:WaitForChild('Ragdolled')


hum.StateChanged:Connect(function(OldState, NewState)
	if newState == Enum.HumanoidStateType.Freefall then
		task.spawn(function()
			local humHeight = root.Position.Y
			repeat
				task.wait()
			until humHeight <= humHeight - 9
			replicatedStorage.RagdollServer:FireServer(char)
		end)
	elseif NewState ~= Enum.HumanoidStateType.Freefall and NewState ~= Enum.HumanoidStateType.Jumping then
		task.delay(5, function()
			if hum:GetState() == Enum.HumanoidStateType.Physics then
				replicatedStorage.GetUp:FireServer(char)
				script.PlayAnimation:FireServer()
			end
		end)
	end
end)

I’m not too keen about having long waits inside an event handler. In general, an event handler is like a hardware interrupt service routine: Get in and get out, fast.

FYI, you can play animations from the client and it will replicate to all clients. No need to send an event to the server to start an animation.

(still not resolved) Thanks for the information, it didn’t ragdoll at all for some reason, no errors.

Is there any way to do it???

Try this:

hum.StateChanged:Connect(function(OldState, NewState)
	if NewState == Enum.HumanoidStateType.Landed then
		local Height = -root.Velocity.Y
		if Height >= 10 then
			replicatedStorage.RagdollServer:FireServer(char)
		end
	end
end)

You can just think like coding a fall damage (I stole it on youtube)

1 Like

This should work fine.

And sorry to OP I had to go to school.

Tysm! Worked perfectly!!!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.