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.
--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)
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)
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)