How to switch landing animations based on time in air

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!

I want to make the avatar land lightly with a light landing animation when the player has been in the air for less than so much time and land heavily with a heavy landing animation when the player has been in the air over a certain amount of time.

  1. What is the issue? Include screenshots / videos if possible!

Tried several different ways, doesn’t behave as expected. Currently when I jump the light landing animation plays everytime and it only lands lightly never heavily.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have tried several ways but cant get any to work… Would anyone be willing to look at the code and tell me what’s wrong with it? Thank you very much in advance.


local char = script.Parent
local hum = char:WaitForChild(("Humanoid"))

local LightLandAnim = Instance.new("Animation")
local ca = tostring(script:WaitForChild("LightLandAnim").AnimationId)
LightLandAnim.AnimationId = ca

local HeavyLandAnim = Instance.new("Animation")
local ca = tostring(script:WaitForChild("HeavyLandAnim").AnimationId)
HeavyLandAnim.AnimationId = ca


local ShouldHeavyLand = false
local StartTime 


--code to switch between light land and heavy land animation

hum.StateChanged:Connect(function(OldState,NewState)
	if NewState == Enum.HumanoidStateType.Freefall then
		StartTime = tick()
		delay(.5, function()
			if tick() - StartTime >= .5 and hum:GetState() == Enum.HumanoidStateType.Freefall then

				ShouldHeavyLand = true

			else

				ShouldHeavyLand = false

			end
		end)
	elseif hum:GetState() ~= Enum.HumanoidStateType.Freefall then

	end
end)


script.Parent.Humanoid.StateChanged:Connect(function(_,state)
	if state == Enum.HumanoidStateType.Landed and ShouldHeavyLand == true then
		
		local playAnim = char.Humanoid:LoadAnimation(HeavyLandAnim)
		playAnim:Play()
       wait(1)
		playAnim:Stop() 
		
	else
		local playAnim = char.Humanoid:LoadAnimation(LightLandAnim)
		playAnim:Play()
		wait(1)
		playAnim:Stop() 
		
	ShouldHeavyLand = false
	end

end)


2 Likes

at this part you shouldn’t use only else, because it will run every time the state is changed and isn’t landed. You can do

if state == Enum.HumanoidStateType.Landed then
	if ShouldHeavyLand == true then
		local playAnim = char.Humanoid:LoadAnimation(HeavyLandAnim)
		playAnim:Play()
		wait(1)
		playAnim:Stop() 
	else
		local playAnim = char.Humanoid:LoadAnimation(LightLandAnim)
		playAnim:Play()
		wait(1)
		playAnim:Stop() 
		
		ShouldHeavyLand = false
	end
end

or just change else to elseif state == Enum.HumanoidStateType.Landed

Oh thank you! of course! That fixed it running everytime the state changed.

I also put the ShouldHeavyLand = false at the end of the first if statement.

But now I have a problem where it always does a heavy landing. I printed ShouldHeavyLand at the end of the freefall check, see:


hum.StateChanged:Connect(function(OldState,NewState)
	if NewState == Enum.HumanoidStateType.Freefall then
		StartTime = tick()
		delay(0.5, function()
			if tick() - StartTime >= 0.5 and hum:GetState() == Enum.HumanoidStateType.Freefall then
				
				ShouldHeavyLand = true
				
			else

				ShouldHeavyLand = false

			end
		end)
	end
	print(ShouldHeavyLand)
end)

And I get this out put when jumping and walking off a ledge:

22:30:43.685 :arrow_forward: false (x2) - Client - LandLight :39
22:30:44.210 :arrow_forward: true (x2) - Client - LandLight :39
22:31:10.143 :arrow_forward: false (x5) - Client - LandLight :39
22:31:19.195 :arrow_forward: true (x2) - Client - LandLight :39
22:31:24.780 :arrow_forward: false (x2) - Client - LandLight :39
22:31:25.609 :arrow_forward: true (x2) - Client - LandLight :39

So i’ve learned from you that the state may be changed multiple times in the air… but I don’t see why it always ends on false (a heavy landing…). I guess if the state is changed multiple times then… it’s not recording the full time from leaving the ground to landing again. But why would the state be changed so many times in the air? Is this just a fact of StateChanged and should i try to switch over to something else (i’ve read about humanoid.floormaterial in passing) or is it a fixable problem with the code? thankk you in advance

I found this alternative by the way!


local char = script.Parent
local hum = char:WaitForChild(("Humanoid"))
local root = hum.Parent:FindFirstChild("HumanoidRootPart")

local LightLandAnim = Instance.new("Animation")
local ca = tostring(script:WaitForChild("LightLandAnim").AnimationId)
LightLandAnim.AnimationId = ca

local HeavyLandAnim = Instance.new("Animation")
local ca = tostring(script:WaitForChild("HeavyLandAnim").AnimationId)
HeavyLandAnim.AnimationId = ca


-- when landing, check the downward velocity if it is over 100 play different animation (SO IT IS POSSIBLE TO GET VELOCITY)
script.Parent.Humanoid.StateChanged:Connect(function(_,state)
	if state == Enum.HumanoidStateType.Landed then
		
	-- if dashing, then dont play landing animation
		if game.Players.LocalPlayer.Character:FindFirstChild("Dashing") then 
			return end
		
		local fallVelocity = -root.Velocity.Y
		if fallVelocity > 100 then
	
			
		print(fallVelocity)
		local playAnim = char.Humanoid:LoadAnimation(HeavyLandAnim)
		playAnim:Play()
       	wait(1)
		playAnim:Stop() 
			

		else
		local playAnim = char.Humanoid:LoadAnimation(LightLandAnim)
		playAnim:Play()
		wait(1)
		playAnim:Stop() 
			
			
		end
		
	end

end)

I figured there must be a way to check velocity but couldnt find it at first on the forum. This is definitely simpler.

Thanks! for your help!

1 Like

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