Adding a Landing Animation to the default Animate script

So I wanted to add some custom animations for my game, and I had planned to do an animation for hitting the ground when falling beyond a certain distance with the default Animate script, but even though I could get the animation to play by changing the Freefall function to as follows

function onFreeFall()
	if (jumpAnimTime <= 0) then
		playAnimation("fall", fallTransitionTime, Humanoid)
	end
	pose = "FreeFall"
	
	--[[Humanoid.StateChanged:Connect(function(old, new)
		if old == Enum.HumanoidStateType.Freefall and new == Enum.HumanoidStateType.Landed then
			if currentAnimInstance and currentAnimInstance.Name == "FallAnim" then
				playAnimation("land", 0.1, Humanoid)
				pose = "Landed"
			end
			
		end
	end)]]
end

(noted out parts are the landing animation which did work)

However, because I did it like this, it uses the default function of the Animate script

playAnimation(“animID”, fadingTime, humanoid)

and I can’t adjust the speed with this. The animation plays too quickly for some reason and I’m unsure how to change this and how I would check how far a player has fallen since I don’t want this animation to play whenever they jump 10cm.

1 Like

yo, so there are many ways but one of the easy ways of doing it can be getting how much time has passed since the player jumped or is free falling

local free_fall_Time = 1 -- time it takes to play the fall animation

local Track_Time = tick() -- sets the tick

Humanoid.StateChanged:Connect(function(_, STATE)
   if STATE == Enum.HumanoidStateType.Jumping or STATE == Enum.HumanoidStateType.Freefall then
    Track_Time = Tick()
 elseif Humanoid:GetState() ~= Enum.HumanoidStateType.FreeFall then
    local Stop_Time = tick()

    if (Stop_Time - Track_Time ) > free_fall_Time then
        playanimtion()
    end

   end
end)
2 Likes

You call track:Play(fadeTime, 1, speed) (the third argument tweaks playback speed) or after track:Play immediately do track:AdjustSpeed(speed) to slow down your land animation AnimationTrack, AnimationTrack:AdjustWeight then use humanoid.StateChanged
(fires for freefall > landed HumanoidStateChanged) to save the Y-position on Freefall and compare it on Landed, only running your land anim if startY - endY exceeds your studs threshold, stateType

1 Like

yea except the default animate script uses its own playAnimation function which doesnt support a speed variable. I could just use normal :Play() but I want to try and keep everything organized and uniform since just switching it for one animation would be weird.

Hm? Well just tweak it to accept an optional speed argument and forward it to the AnimationTrack:Play(fadeTime, weight, speed) call, since Play already supports a speed multiplier as its third parameter it will default to 1 and it lets you slow down only your land anim while keeping every call uniform. If you want to tweak playback you can also call AnimationTrack:AdjustSpeed(speed) afterward, every animation goes through that but you get full control over speed when you need it.

used this and fit it in my script but I notice it spams the logs with multiple checks at a time. Also, after i hit the ground from a valid fall (a time >= free_fall_time) then after the land animation my character just goes into default pose with no animations until I press a movement key.
image

function onFreeFall()
	if (jumpAnimTime <= 0) then
		playAnimation("fall", fallTransitionTime, Humanoid)
	end
	pose = "FreeFall"
	
	
	local free_fall_Time = 1 -- time it takes to play the fall animation

	local Track_Time = tick() -- sets the tick

	Humanoid.StateChanged:Connect(function(old, new)
		if new == Enum.HumanoidStateType.Jumping or new == Enum.HumanoidStateType.Freefall then
			print("falling")
			Track_Time = tick()
		elseif Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall then
			print('landed passed')
			local Stop_Time = tick()
			
			if (Stop_Time - Track_Time) > free_fall_Time then
				playAnimation("land", 0.1, Humanoid, 1)
				print('passed time')
				pose = "Landed"
			end
		end
	end)
end

yes sorry well i forgot to check if the player actually lands so i just changed it up a bit…

local free_fall_Time = .7 -- time it takes to play the fall animation
local Track_Time = tick() -- sets the tick

local Animation

local function CreateAnimation()
	if not Character:FindFirstChild("FallAnim") then
		Animation = Instance.new("Animation")
		Animation.Name = "FallAnim"
		Animation.AnimationId = "rbxassetid://ID"
		Animation.Parent = Character
	else
		Animation = Character:FindFirstChild("FallAnim")
	end
		
	local Track: AnimationTrack = Animator:LoadAnimation(Animation)

	Track:Play()
end

Humanoid.StateChanged:Connect(function(_, STATE)
	if STATE == Enum.HumanoidStateType.Jumping or STATE == Enum.HumanoidStateType.Freefall then
		Track_Time = tick()
		print("falling or jumpinhg")
	elseif Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() == Enum.HumanoidStateType.Landed then
		local Stop_Time = tick()
		print("landed")
		if (Stop_Time - Track_Time ) > free_fall_Time then
			CreateAnimation()
			warn("landed but play animation")
		end

	end
end)

this should work as intended

I appreciate it. I modified it a bit since I didn’t need the CreateAnimation() function as I just added my land anim as a value in the table so it looks like this now

function onFreeFall()
	if (jumpAnimTime <= 0) then
		playAnimation("fall", fallTransitionTime, Humanoid)
	end
	pose = "FreeFall"
	
	
	local free_fall_Time = 1 -- time it takes to play the fall animation
	local Track_Time = tick() -- sets the tick

	
	local Animation = animTable["land"][1].anim

		local Track: AnimationTrack = Animator:LoadAnimation(Animation)


	Humanoid.StateChanged:Connect(function(_, STATE)
		if STATE == Enum.HumanoidStateType.Jumping or STATE == Enum.HumanoidStateType.Freefall then
			Track_Time = tick()
			print("falling or jumping")
		elseif Humanoid:GetState() ~= Enum.HumanoidStateType.Freefall and Humanoid:GetState() == Enum.HumanoidStateType.Landed then
			local Stop_Time = tick()
			print("landed")
			if (Stop_Time - Track_Time ) > free_fall_Time then
				print("landed worked")
				Track:Play()
			end
		end
	end)
end

it plays and continues my idle after now, though there is this weird issue where if the first jump of my character ends up landing and firing the land animation then it looks like and smooth, but if I have jumped prior to a fall that procs the land animation it has a weird cut. Here’s a small video showing this


From what I can tell, this issue is likely due to the script attempting to play the animation multiple times which I see in the output. For some reason, the first time I jump after play testing the log only does one of each message as follows:
image

However, if I jump more than once (If I have jumped or been airborne more than one time prior to a landing) then it displays this (this is all from one jump):
image

I’ll tweak it around a bit to see if a debounce or smth can help but if u have an idea that would be great. Thanks regardless.

So I added print(“freefall function run”) to just when the onFreefall() function is run which is the default function that runs when the player’s freefall starts and I notice it is being run multiple times when the player jumps. I’ll try different locations for the script but otherwise I might need a debounce for the freefall function.

Ok pretty sure I fixed it by just removing the onLand() function and just having the statechange:connect be a part of the script on its own to detect the landing.

1 Like

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