Animation Length is 0?

Hello, the following script is supposed to play an animation for an item drop upon player action (indicated by function ChestPools:spawnItem). The animation also has several keyframes spanning 0.6 sec. However, the animation length is returning a length of 0 and is not playing (even without adjusting the speed to 0).

Also optimization is not important, as I am more concerned with solving the current problem! Thanks!

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local ChestPools = {}

local Items = {}
Items["Common"] = {"Apple"}
Items["Rare"] = {"GreenApple"}
Items["Legendary"] = {"DecayedApple"}

-- Load and store animations
local function loadAnimation(item)
    local itemDrop = Instance.new("Animation")
    itemDrop.AnimationId = "rbxassetid://128752945782630"
    
    local animator = Instance.new("Animator")
    animator.Parent = item:WaitForChild("Humanoid")
    local track = animator:LoadAnimation(itemDrop)
    track.Name = "itemDrop"
    return track
end



function getItems(rarities)
    local items = {}

    for _, rarity in rarities do
        
        items[rarity] = {}
        
        for _, item in Items[rarity] do
            
            table.insert(items[rarity], item)
            
        end

    end

    return items
end

ChestPools["Normal"] = {
    
    Chances = {
        Common = 70.0,
        Rare = 20.0,
        Legendary = 10.0
    },
    Pool = getItems({"Common", "Rare", "Legendary"})
    
}

ChestPools["Big"] = {}
ChestPools["Legendary"] = {}

function ChestPools:RandomPull(chest)
    --Pull a random rarity and an item ascociated with the rarity
    local rarity = nil
    local random = math.random(1, 100)
    local counter = 0
    local chestType = chest:GetAttribute("chestType")
    
    for rarityKey, rarityChance in ChestPools[chestType].Chances do
        counter = counter + rarityChance
        if random <= counter then
            rarity = rarityKey
            break
        end
    end
    
    local pool = ChestPools[chestType].Pool[rarity]
    local item = pool[math.random(1, #pool)]
    
    local spawnPos = chest.PrimaryPart.Position + Vector3.new(0, 0, 0)
    local item = ReplicatedStorage.Items[rarity][item]:Clone()
    item:SetPrimaryPartCFrame(CFrame.new(spawnPos) * CFrame.Angles(0, 0, 0))
    
    local tracks = loadAnimation(item)
    
    return {item, tracks}
end

function ChestPools:spawnItem(chest, itemInfo)
    local item = itemInfo[1]
    local itemRarity = item:GetAttribute("Rarity")
    local animationTrack = itemInfo[2]
    
    task.wait(0.5)
    
    item.Parent = workspace.Items[itemRarity]

    print("Loaded animation track:", animationTrack)
    animationTrack:Play()
    print("Started playing animation track")
    print(animationTrack.Length)
    task.wait(animationTrack.Length/2)
    print(animationTrack)
    while workspace:Raycast(item.RaycastPart.Position, -item.RaycastPart.CFrame.UpVector * ((item.RaycastPart.Size.Y/2)+0.1)) == nil do
        task.wait()
    end
    animationTrack:AdjustSpeed(0)
    print("Animation track finished playing")
    
end

return ChestPools

EDIT:
Each chest has a script that calls RandomPull (also calling loadAnimation). This should pre-load the animation as soon as the chest is created and the animation will wait to play until a player interaction. All of the items use the same animation and a new animation instance is created for each chest/item. I have tested this animation before and it worked perfectly fine (animation length and all). It just does not want to work with the random factor of the items for some reason and I cant figure out why.

1 Like

The .Length property of AnimationTracks return 0 if they haven’t loaded in yet.

Since your code is reliant on the length, you can try waiting until it returns a length > 0:

print("Loaded animation track:", animationTrack)
-- tries to repeatedly play
-- until it loads
repeat task.wait() animationTrack:Play() until animationTrack.Length > 0
print("Started playing animation track")
print(animationTrack.Length)
task.wait(animationTrack.Length/2)
print(animationTrack)

This is what I usually do, of course you can try pre-loading the animations but (usually) this works too. Might seem a little hacky, probably is, but the animation should eventually load.

The animation should already be pre-loaded in the loadAnimation function above which is called in PullRandom (which will be called later when the player interacts with a chest). Doing your solution will wait infinitely.

Another thing: each chest has a script that calls RandomPull (also calling loadAnimation). This should pre-load the animation as soon as the chest is created and the animation will wait to play until a player interaction. All of the items use the same animation and a new animation instance is created for each chest/item. I have tested this animation before and it worked perfectly fine (animation length and all). It just does not want to work with the random factor of the items for some reason and I cant figure out why.

1 Like

Why are you creating a new Animator (there’s already one in every humanoid) ?

Does the problem happen in any other animation or is it only this one? ( try switching the AnimationId in the same code )

Try switching StreamingEnabled off.

Look in the asset manager and see if the animation uploaded successfully.

You are right about the Animator part. I just manually added them into Humanoid now as the items did not have Animator originally (does not solve the problem though).

The animation does not play regardless of which animation I tell it to play on the item.

Switching off StreamingEnabled does not seem to do anything.

And, about the asset manager part, I did not upload the animation. I created the animation myself in Roblox and saved it to Roblox and used it ID. I don’t know if it is supposed to be uploaded but it worked perfectly fine without that before on multiple different items (It is in the revamped asset manager though if that’s what you mean).

Not sure why @Downrest’s reply doesn’t solve your issue. Another way you could approach this problem is to preload it with ContentProvider.

I’m 99% sure that this is the fix. Man, I hate debugging.
The best thing? It’s actually mentioned in the doc ( yeah i know no ones actuall remembers every single word in the doc):
image

The fix:

-- in ChestPools:RandomPull(chest)
	local item = ReplicatedStorage.Items[rarity][item]:Clone()
	
	item:PivotTo(CFrame.new(spawnPos) * CFrame.Angles(0, 0, 0))
	
	-- !!!
	item.Parent = workspace
	local track,animator = ChestPools.loadAnimation(item)
	
	-- hide the item again
	item.Parent = game
2 Likes

you fool

didn’t read through any of the replies btw,
if you try getting the length of a track straight after loading, it might (and probably will) return 0

this will happen EVEN if you preload all the animations in a table and then fetch that
well, not all the time, but sometimes

the fix to this is to:

while track.Length > 0.5 do -- idk if the number has any impact,
    -- i just do something larger than 0 all the time just to be sure
   task.wait()
end

Thank you! I don’t know how I didn’t see this after browsing the documentation prior to this post. This completely solves the problem I was having.

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