How's this to detect fall damage?

I created a fall damage script that hasn’t failed me once and is used on the client, but is there any more efficent ways to check?

while true do
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {Character}
	
	local r = workspace:Raycast(Root.Position, Vector3.new(0, -4, 0), params)
	
	if not r then
		Falling.Value = true
	else
		Falling.Value = false
	end
	
	task.wait()
end

since I’m using a loop. I can’t just detect the humanoid states such as falling and landed because you ragdoll when you fall and so if you were to fall, hit something, ragdoll, then fall again while stunned (ragdolled,) then it wouldn’t do extra damage. That was the only problem using statetypes. the method I use now works all the time no matter what state the humanoid is in. I just fear that this loop might hinder performance a bit.

4 Likes

single raycast every frame doesn’t matter much

of course you can check microprofiler or script performance for sure.

3 Likes

I personally opt for a different approach, whenever a character lands on the ground their humanoid state briefly changes to “landed”. When this happens I just check the AssemblyLinearVelocity of their HumanoidRootPart (which stays the same while the character’s humanoid has just landed) and deal damage if it’s high enough.

like this:

Connection = Humanoid.StateChanged:Connect(function(OldState, NewState)
		if NewState == Enum.HumanoidStateType.Landed then
			local YVelocity = HRP.AssemblyLinearVelocity.Y

			if YVelocity <= -100 then
				local Damage = (math.abs(YVelocity) - 100) * 2
				
				if Damage >= 50 then
					Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
					Ragdoll:FireServer()
					
					task.delay(5, function()
						Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
					end)
				end
				
				FallDamageEvent:FireServer(Damage)
			end
		end
	end)

Your approach is good as well, just up to preference!!

4 Likes

This is my first time ever on making a fall damage script. So, it might have a few bugs it but with my few minutes of testing it hasn’t have much issue so far

Fall Detection script(Local)

-- Note this script is in StarterCharacterScripts

local FallDamageEvent = game.ReplicatedStorage.FallDamageEvent

local startTime = 0

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

local jumping = false
local isStanding = true
local falling = false

local jumpBuffer = .2

local damageRange = 1 -- The ammount of time in which the player was in the air to initiate fall damage to begin
local deathRange = 10 -- If the player greater or equal to the range the player will automatically die

local baseFallDamge = 2 -- The ammount of health
local damageMultiplier = 2 -- The ammount to increase
local increaseDuration = 0.5 -- The ammount of time passed to increase the damage

local function fallDamageCalculation()
	print("Calc")
	local curr = tick()
	
	local sum = curr - startTime
	
	print(sum)
	local function getDamageResult(t,timePassed)
		local result = baseFallDamge
		for i = 0,timePassed do
			result = result * damageMultiplier
			print(result)
		end
		return result
	end
	
	if sum > deathRange then
		FallDamageEvent:FireServer(99999999999999)
	else
		if sum > damageRange then
			local airTimeExtra = math.floor(math.abs(sum) / increaseDuration) - damageRange
			print(airTimeExtra, "Time")
			local damage = getDamageResult(sum,airTimeExtra)

			FallDamageEvent:FireServer(damage)
		else
			return
		end
	end
	
end

humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
	if humanoid.FloorMaterial == Enum.Material.Air and humanoid.Sit ~= true and humanoid.PlatformStand ~= true then
		print("Air")
		
		
		startTime = tick()
		isStanding = false
		task.delay(.4,function()
			if humanoid.FloorMaterial == Enum.Material.Air then
				falling = true
			end
		end)
		
		
	else
		
		if falling then
			print("Falling")

			fallDamageCalculation()
		else
			
		end
		
		isStanding = true
		startTime = 0
		falling = false
		jumping = false
		
	end
end)

game['UserInputService'].InputBegan:Connect(function(input,gproc)
	if not gproc then
		if input.KeyCode == Enum.KeyCode.Space then
			if jumping == false then
				jumping = true
				
				task.delay(jumpBuffer,function()
					jumping = false
					if humanoid.FloorMaterial == Enum.Material.Air then
						falling = true
					else
						startTime = 0
					end
				end)
			end
		end
	end
end)

Fall Damage script(Server)

game.ReplicatedStorage.FallDamageEvent.OnServerEvent:Connect(function(player,damage)
	local humanoid : Humanoid = player.Character:FindFirstChild("Humanoid")
	
	humanoid:TakeDamage(damage)
end)

Anyways hope this works or helps you find a solution. Happy Coding & good luck! :smiley: