Replication of old animation blending

This piece of code replicates the old animation blending system before the new engine update that changed how animations are blended using their respective weight. It is for those that prefer to keep the structure of their custom animation system without having to make extra modifications in their script.

-- local script
local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local playingAnim = {}

-- adds existing animations to the playingAnim table
for i, anim in ipairs(hum:GetPlayingAnimationTracks()) do
	table.insert(playingAnim, anim)
end

-- fires when a new animation is played
function animPlayed(anim)
    if table.find(playingAnim, anim) then
		return
	end
	local con 
	-- adds the animation to the playingAnim table
	table.insert(playingAnim, anim)

	-- adjusts the weight of the previous playing animations of the same priority to 0.001, thus stopping it
	for i, otherAnim in ipairs(playingAnim) do
		if otherAnim.Priority == anim.Priority and otherAnim ~= anim then
			otherAnim:AdjustWeight(0.001)
		end
	end
	
	-- fires the animStopped function
	con = anim.Stopped:Connect(function()
		animStopped(anim)
		con:Disconnect()
	end)
end

-- fires when an animation is stopped
function animStopped(anim)
	local index = table.find(playingAnim, anim) 
	local divisions = {} -- container for tables that represent every animation priority

	if index then
		table.remove(playingAnim, index) -- removes the stopped animation from the playingAnim table
		
		-- creates a table for every animation priority that belongs to a playing animation
		for i, otherAnim in ipairs(playingAnim) do
			divisions[tostring(otherAnim.Priority)] = {}
		end
		
		-- adds animations to each priority table according to their own priority
		for priority, t in pairs(divisions) do
			for i, otherAnim in ipairs(playingAnim) do
				if priority == tostring(otherAnim.Priority) then
					table.insert(t, otherAnim)
				end
			end
		end
		
		-- adjusts the last played animation's weight of each priority table to 1 
		for priority, t in pairs(divisions) do
			local lastPlayedAnim = t[#t]

			lastPlayedAnim:AdjustWeight(1)
		end
	end
end

hum.AnimationPlayed:Connect(animPlayed)
13 Likes

Its quite nice to see a post like this, since Im sure a lot of developers are having issues with the new update.

Though this isnt a prefect solution:
Lets say that animation 1 rotates the Left Arm up with priority Action.
Animation 2 rotates the Right Arm up with priority Action.
Animation 1 would still get stopped in favor of animation 2.

(Or at least I think so, I cant confirm because of the current outage)

1 Like

Although tedious, you can solve that issue by creating extra animations and using some if statement logic:

local anim1 = hum:LoadAnimation(RightUp)
local anim2 = hum:LoadAnimation(LeftUp)
local anim3 = hum:LoadAnimation(BothUp)

function animPlayed(anim)
	if anim == anim1 or anim == anim2 then
		anim.Stopped:Connect(function()
			animStopped(anim)
		end)	
		-- detects if a hand is already up
		if anim1.IsPlaying and anim2.IsPlaying then
			anim3:Play()
		end
	end
end

function animStopped(anim)
	if anim == anim1 or anim == anim2 then
		anim3:Stop()
	end
end

hum.AnimationPlayed:Connect(animPlayed)

Currently it is impossible to manually change the weight of individual keyframes, meaning that this is the best solution where an entirely new animation is created for the action of this specific context. Alternatively, you can just choose to adapt to the new animation blending change and work from there if your scripts do not need extensive modifications.

2 Likes