Blending Walking and Sprinting Animations

I’m trying to smoothly transition between a set of walking and sprinting animations using :AdjustWeight, but I get a slight stuttering effect when I do so. I blend the animations by initially playing them with a close to zero weight and adjusting their weight based on the direction of the character’s movement. I think my issue might occur because the walking and sprinting animations have a different length but I can’t think of a way to compensate for this. I tried adjusting the TimePosition of the tracks when switching states but that didn’t work as I’m probably doing something wrong.

Thank you!

https://gyazo.com/d9b351c8327e6e8dfc2d89e50062442b

--lerptracks  is a table with all the animations in it
--playingtrack is the track that is supposed to be playing

game:GetService("RunService"):BindToRenderStep("WalkCycle", Enum.RenderPriority.Character.Value, function(dt)
	
	
	
	if humanoid.Health > 0 then
		
	
		for i =1,#lerptracks do
			local track = lerptracks[i];
			if(playingtrack==nil) then
				track:AdjustWeight(0.0000101,0.2);
				
				
			else
				
				
				if(track.Name == playingtrack.Name) then
				
				track:AdjustWeight(1,0.15);
				
				else
					track:AdjustWeight(0.0000101,0.15);
					
				end
			end
		end
	end
	end)

characterState.Changed:Connect(function()
	local ch = playingtrack.TimePosition/playingtrack.Length
for i,v in pairs(lerptracks) do
	if(v~=playingtrack) then
		v.TimePosition = v.Length*ch;
	end
end


end)
7 Likes

Can you show us the rest of the script that pertaining to animations?

(The logic behind determining when to switch animations, switching animations, etc.)

Instead of manually adjusting weights, simply use the first argument of animationtrack:Play()/animationtrack:Stop() to make the transition smoother.

local smoothness = 0.3 -- how slowly animation transforms into the first pose, the first time it is played.


local function run(bool)
if bool then
sprintanim:Play(smoothness)
walkanim:Stop(smoothness)
else
sprintanim:Stop(smoothness)
walkanim:Play(smoothness)
end

alternatively, if you don’t want to use that, you can try weighted lerps.

local sprintweight = 1 -- whatever you want it to start as
local sprintweightgoal
local sprinting = false -- variable if player is sprinting or not

local function lerp(number, numbergoal, increment)
    return number + (numbergoal - number) * increment
end


runservice.Heartbeat:connect(function()
if sprinting == true then
sprintingweight = lerp(sprintingweight, sprintingweightgoal, 0.15) 
else
sprintingweight = lerp(sprintingweight, 0, 0.15) 
end
sprintanim:AdjustWeight(sprintingweight)
end)
6 Likes

here, but I don’t think there are any problems with those sections




local lastTick = tick()
local playingtrack  = "";
local lerptracks = {};

	
	
	
game:GetService("RunService"):BindToRenderStep("WalkCycle", Enum.RenderPriority.Character.Value, function(dt)
	local deltaTime = tick() - lastTick
	lastTick = tick()

	
	if humanoid.Health > 0 then
		
	

	
		for i =1,#lerptracks do
			local track = lerptracks[i];
			if(playingtrack==nil) then
				track:AdjustWeight(0.0000101,0.2);
				
				
			else
			
				if(track.Name == playingtrack.Name) then
				
				track:AdjustWeight(1,0.15);
				
				else
					track:AdjustWeight(0.0000101,0.15);
				
				end
			end
		end
	end
	end)
	
local transtime = 0.15
function stop()

end

local anims = {
	["NOGUN"] = {
	["None"] = {["14"] = {3461368704,3461372779,3461382991,3461385952,3461395705,3461399865,3461532917,3461565773}},
	["Sprint"] = {["21"] = {3470545628,3470565804,3470571750,03470579909,3470585309,3470589962,3470594840,3470599565}},
	
	
	}
	
}

local tracks = {};
local sprinttracks = {};
local nonetracks = {};
local walklen = 0;
for i = 1,#anims.NOGUN.None["14"] do
	local id = tostring(anims.NOGUN.None["14"][i]);
	
local animation = Instance.new("Animation")
			
		
animation.AnimationId = "http://www.roblox.com/Asset?ID="..id;
animation.Name = id;
	local track  = player.Character.Humanoid:LoadAnimation(animation)
	table.insert(lerptracks,track);
	track:Play(0,0.0000101,1);
	table.insert(nonetracks,track)
	tracks[id] = track;
	walklen = track.Length;
end

for i = 1,#anims.NOGUN.Sprint["21"] do
	local id = tostring(anims.NOGUN.Sprint["21"][i]);
	
local animation = Instance.new("Animation")
			
		
animation.AnimationId = "http://www.roblox.com/Asset?ID="..id;
animation.Name = id;
	local track  = player.Character.Humanoid:LoadAnimation(animation)
	table.insert(lerptracks,track);
	table.insert(sprinttracks,track)
track:Play(0,0.0000101,1);
	
	tracks[id] = track;
end




local gunstatus = "NOGUN";
local oldhash = "0 0";
function change()

	local walk = tostring(floor(humanoid.WalkSpeed));
	
	local curs = character.State.Value--"None";--
	local localDirection = BASE.CFrame:vectorToObjectSpace(humanoid.MoveDirection*Vector3.new(1,0,1))
	
	localDirection = Vector3.new(floor(localDirection.X*10 + 0.5),floor(localDirection.Y*10 + 0.5),floor(localDirection.Z*10 + 0.5));
	local hash = tostring(localDirection.X).." "..tostring(localDirection.Z);
	if(hash==oldhash) then
	
	end
	oldhash = hash;
	
	if hash == "0 -10" then
		--forwards
		
		
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][1])];
	
	elseif hash == "0 0" then
	
	playingtrack = nil;
	elseif hash == "0 10" then
		--S
	
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][2])];
	elseif hash == "-10 0" then
		--left
	
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][4])];
	elseif hash == "10 0" then
		--right
		
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][3])];
	elseif hash == "7 7" then
		--south right
		
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][5])];
	elseif hash == "-7 7" then
		--south left
	
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][6])];
	
	elseif hash == "-7 -7" then
		--north left
	

	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][8])];
	elseif hash == "7 -7" then
		--north left
		
	
	playingtrack = tracks[tostring(anims[gunstatus][curs][walk][7])];
	
	end
end
humanoid.Changed:Connect(function(MoveDirection)
	humanoid.WalkSpeed = defaultSpeed * stances[state.Value][1]
	change()
end)

state.Changed:Connect(function(val)
	
	
	if(playingtrack~=nil) then
	local ch = playingtrack.TimePosition/playingtrack.Length
for i,v in pairs(lerptracks) do
	if(v~=playingtrack) then
		v.TimePosition = v.Length*ch;
	end
end
	end


humanoid.WalkSpeed = defaultSpeed * stances[state.Value][1]
	change()
end)
2 Likes