Falling Animation Not Playing

For some reason the falling animation doesn’t play if the player walks off an edge but works when jumping. I was having issues with the falling animations not playing after jumping so I made a script to patch that which may be causing the issue:

Video:

Scripts:
Anime:

local Figure = script.Parent
local Torso = Figure:WaitForChild("Torso")
local RightShoulder = Torso:WaitForChild("Right Shoulder")
local LeftShoulder = Torso:WaitForChild("Left Shoulder")
local RightHip = Torso:WaitForChild("Right Hip")
local LeftHip = Torso:WaitForChild("Left Hip")
local Neck = Torso:WaitForChild("Neck")
local Humanoid = Figure:WaitForChild("Humanoid")
local pose = "Standing"

local currentAnim = ""
local currentAnimInstance = nil
local currentAnimTrack = nil
local currentAnimKeyframeHandler = nil
local currentAnimSpeed = 1.0
local animTable = {}
local animNames = { 
	idle = {
		{ id = "http://www.roblox.com/asset/?id=15731151612", weight = 9 },
		{ id = "http://www.roblox.com/asset/?id=15731151612", weight = 1 }
	},
	walk = { { id = "http://www.roblox.com/asset/?id=15595131171", weight = 10 } },
	run = { { id = "http://www.roblox.com/asset/?id=15733676048", weight = 10 } },
	jump = { { id = "http://www.roblox.com/asset/?id=15595113216", weight = 10 } },
	fall = { { id = "http://www.roblox.com/asset/?id=18567664383", weight = 10 } },
	climb = { { id = "http://www.roblox.com/asset/?id=180436334", weight = 10 } },
	sit = { { id = "http://www.roblox.com/asset/?id=178130996", weight = 10 } },
	toolnone = { { id = "http://www.roblox.com/asset/?id=182393478", weight = 10 } },
	toolslash = { { id = "http://www.roblox.com/asset/?id=129967390", weight = 10 } },
	toollunge = { { id = "http://www.roblox.com/asset/?id=129967478", weight = 10 } },
	wave = { { id = "http://www.roblox.com/asset/?id=128777973", weight = 10 } },
	point = { { id = "http://www.roblox.com/asset/?id=128853357", weight = 10 } },
	dance1 = {
		{ id = "http://www.roblox.com/asset/?id=17465309146", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=17465309146", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=17465309146", weight = 10 }
	},
	dance2 = {
		{ id = "http://www.roblox.com/asset/?id=182436842", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=182491248", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=182491277", weight = 10 }
	},
	dance3 = {
		{ id = "http://www.roblox.com/asset/?id=182436935", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=182491368", weight = 10 },
		{ id = "http://www.roblox.com/asset/?id=182491423", weight = 10 }
	},
	laugh = { { id = "http://www.roblox.com/asset/?id=129423131", weight = 10 } },
	cheer = { { id = "http://www.roblox.com/asset/?id=129423030", weight = 10 } }
}
local dances = {"dance1", "dance2", "dance3"}

local emoteNames = { wave = true, point = true, dance1 = true, dance2 = true, dance3 = true, laugh = true, cheer = true }

-- Configure animation set for a given name and file list
function configureAnimationSet(name, fileList)
	if animTable[name] then
		for _, connection in pairs(animTable[name].connections) do
			connection:disconnect()
		end
	end
	animTable[name] = { count = 0, totalWeight = 0, connections = {} }

	local config = script:FindFirstChild(name)
	if config then
		table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))
		table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))
		local idx = 1
		for _, childPart in pairs(config:GetChildren()) do
			if childPart:IsA("Animation") then
				table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
				animTable[name][idx] = { anim = childPart, weight = childPart:FindFirstChild("Weight") and childPart.Weight.Value or 1 }
				animTable[name].count = animTable[name].count + 1
				animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
				idx = idx + 1
			end
		end
	end

	if animTable[name].count <= 0 then
		for idx, anim in pairs(fileList) do
			animTable[name][idx] = { anim = Instance.new("Animation"), weight = anim.weight }
			animTable[name][idx].anim.Name = name
			animTable[name][idx].anim.AnimationId = anim.id
			animTable[name].count = animTable[name].count + 1
			animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
		end
	end
end

-- Setup animation objects
function scriptChildModified(child)
	local fileList = animNames[child.Name]
	if fileList then
		configureAnimationSet(child.Name, fileList)
	end
end

script.ChildAdded:connect(scriptChildModified)
script.ChildRemoved:connect(scriptChildModified)

for name, fileList in pairs(animNames) do 
	configureAnimationSet(name, fileList)
end    

-- ANIMATION FUNCTIONS

local toolAnim = "None"
local toolAnimTime = 0
local jumpAnimTime = 0
local jumpAnimDuration = 0.3
local toolTransitionTime = 0.1
local fallTransitionTime = 0.3
local jumpMaxLimbVelocity = 0.75

-- Stop all animations and return the old animation
function stopAllAnimations()
	local oldAnim = currentAnim

	if emoteNames[oldAnim] and not emoteNames[oldAnim] then
		oldAnim = "idle"
	end

	currentAnim = ""
	currentAnimInstance = nil
	if currentAnimKeyframeHandler then
		currentAnimKeyframeHandler:disconnect()
	end

	if currentAnimTrack then
		currentAnimTrack:Stop()
		currentAnimTrack:Destroy()
		currentAnimTrack = nil
	end
	return oldAnim
end

-- Set animation speed
function setAnimationSpeed(speed)
	if speed ~= currentAnimSpeed then
		currentAnimSpeed = speed
		currentAnimTrack:AdjustSpeed(currentAnimSpeed)
	end
end

-- Keyframe reached function
function keyFrameReachedFunc(frameName)
	if frameName == "End" then
		local repeatAnim = currentAnim
		playAnimation(repeatAnim, 0.15, Humanoid)
	end
end

-- Play animation based on action
function playAnimation(animName, transitionTime, humanoid)
	local roll = math.random(1, animTable[animName].totalWeight)
	local idx = 1
	while roll > animTable[animName][idx].weight do
		roll = roll - animTable[animName][idx].weight
		idx = idx + 1
	end
	local anim = animTable[animName][idx].anim

	if anim ~= currentAnimInstance then
		if currentAnimTrack then
			currentAnimTrack:Stop(transitionTime)
			currentAnimTrack:Destroy()
		end

		currentAnimSpeed = 1
		currentAnimInstance = anim
		currentAnim = animName

		currentAnimTrack = humanoid:LoadAnimation(anim)
		currentAnimTrack.Priority = Enum.AnimationPriority.Core

		currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
		currentAnimTrack:Play(transitionTime)
	end
end

-- ANIMATION EVENTS

function onRunning(speed)
	if speed > 0.01 then
		playAnimation("walk", 0.1, Humanoid)
		setAnimationSpeed(speed / 16)
		pose = "Running"
	else
		playAnimation("idle", 0.1, Humanoid)
		pose = "Standing"
	end
end

function onDied()
	pose = "Dead"
end

function onJumping()
	playAnimation("jump", jumpAnimDuration, Humanoid)
	jumpAnimTime = jumpAnimDuration
	pose = "Jumping"
end

function onClimbing()
	playAnimation("climb", 0.1, Humanoid)
	setAnimationSpeed(0.25)
	pose = "Climbing"
end

function onGettingUp()
	pose = "GettingUp"
end

function onFreeFall()
	if jumpAnimTime <= 0 then
		playAnimation("fall", fallTransitionTime, Humanoid)
	end
	pose = "FreeFall"
end

function onFallingDown()
	pose = "FallingDown"
end

function onSeated()
	pose = "Seated"
end

function onPlatformStanding()
	pose = "PlatformStanding"
end

function onSwimming(speed)
	if speed > 0.01 then
		pose = "Swimming"
	else
		pose = "Standing"
	end
end

-- Setup events
Humanoid.Died:connect(onDied)
Humanoid.Running:connect(onRunning)
Humanoid.Jumping:connect(onJumping)
Humanoid.Climbing:connect(onClimbing)
Humanoid.GettingUp:connect(onGettingUp)
Humanoid.FreeFalling:connect(onFreeFall)
Humanoid.FallingDown:connect(onFallingDown)
Humanoid.Seated:connect(onSeated)
Humanoid.PlatformStanding:connect(onPlatformStanding)
Humanoid.Swimming:connect(onSwimming)

-- Tool Animation Functions

function playToolAnimation(animName, transitionTime, humanoid, priority)
	stopToolAnimations()
	local anim = animTable[animName][1].anim
	toolAnim = animName

	currentToolAnimTrack = humanoid:LoadAnimation(anim)
	currentToolAnimTrack.Priority = priority
	currentToolAnimTrack:Play(transitionTime)
end

function stopToolAnimations()
	local oldAnim = toolAnim
	toolAnim = "None"
	if currentToolAnimTrack then
		currentToolAnimTrack:Stop()
		currentToolAnimTrack:Destroy()
		currentToolAnimTrack = nil
	end
	return oldAnim
end

-- Handle user input for emotes
function onEmote(emote)
	if emoteNames[emote] then
		playAnimation(emote, 0.1, Humanoid)
	end
end

Humanoid.Emote:connect(onEmote)

-- Main Loop

while true do
	local _, timeElapsed = wait(0.1)
	local moveDir = Humanoid.MoveDirection
	if moveDir.Magnitude > 0 then
		onRunning(moveDir.Magnitude)
	else
		onRunning(0)
	end
end

Double Jump (if it helps):

-- Services and references
local UIS = game:GetService("UserInputService")
local Players = game:GetService("Players")
local StarterPlayer = game:GetService("StarterPlayer")

local player = Players.LocalPlayer
local Character = player.Character or player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

-- Type definitions
type Animator = Animator & {
	LoadAnimation: (self: Animator, animation: Animation) -> AnimationTrack,
}

type AnimationTrack = AnimationTrack & {
	Play: (self: AnimationTrack) -> nil,
	Stop: (self: AnimationTrack) -> nil,
	IsPlaying: boolean,
}

-- Variables
local CanDoubleJump = false
local CanSetCanDoubleJumpToTrue = false
local DoubleJumpAnimation: AnimationTrack? = nil
local Animator: Animator? = nil
local isFirstJump = true

-- Function to load the double jump animation
local function loadDoubleJumpAnimation(): AnimationTrack
	if not DoubleJumpAnimation then
		Animator = Humanoid:FindFirstChild("Animator") or Instance.new("Animator", Humanoid)
		DoubleJumpAnimation = Animator:LoadAnimation(script.Flip)
	end
	return DoubleJumpAnimation
end

-- Function to handle jump requests
local function handleJumpRequest()
	if isFirstJump then
		Humanoid.JumpPower = StarterPlayer.CharacterJumpPower
		isFirstJump = false
	elseif CanDoubleJump then
		Humanoid.JumpPower = Humanoid.JumpPower * 1
		Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		local animation = loadDoubleJumpAnimation()
		animation:Play()
		CanDoubleJump = false
	end
end

-- Function to handle state changes
local function handleStateChange(oldState: Enum.HumanoidStateType, newState: Enum.HumanoidStateType)
	if newState == Enum.HumanoidStateType.Landed then
		CanDoubleJump = false
		CanSetCanDoubleJumpToTrue = true
		Humanoid.JumpPower = StarterPlayer.CharacterJumpPower
		if DoubleJumpAnimation and DoubleJumpAnimation.IsPlaying then
			DoubleJumpAnimation:Stop()
		end
	elseif newState == Enum.HumanoidStateType.Freefall then
		if CanSetCanDoubleJumpToTrue then
			task.wait(0.2)
			CanDoubleJump = true
			CanSetCanDoubleJumpToTrue = false
		end
	end
end

-- Error handling functions
local function onJumpRequestError(err)
	warn("Error in handleJumpRequest: " .. tostring(err))
end

local function onStateChangeError(err)
	warn("Error in handleStateChange: " .. tostring(err))
end

-- Connect events with error handling
UIS.JumpRequest:Connect(function()
	local success, err = pcall(handleJumpRequest)
	if not success then
		onJumpRequestError(err)
	end
end)

Humanoid.StateChanged:Connect(function(oldState, newState)
	local success, err = pcall(handleStateChange, oldState, newState)
	if not success then
		onStateChangeError(err)
	end
end)

Thank you!

did u change the animId for the actual “AnimationId” for the fall animation? or is it only through a script?
image

1 Like

I changed the id for the animation as seen here:

fall = { { id = "http://www.roblox.com/asset/?id=18567664383", weight = 10 } },

I also did change the AnimationID:
image

I see what the problem is, the jumpAnimTime is always set to 0.3 because of the jumpAnimDuration

2 Likes

I changed it to 0 and it worked while walking off the ledge but the animation looks a little different now.

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