im making a shift to sprint but the animation doesnt play when i move if i hold shift before moving and if im holding shift and stop moving it keeps playing. im going insane
local Player = game.Players.LocalPlayer;
local Parent = script.Parent;
local Humanoid = Parent:WaitForChild("Humanoid");
local TweenService = game:GetService("TweenService");
local Sprint = Humanoid:LoadAnimation(script:WaitForChild("Sprint"))
local Sprinting = false
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 80
}):Play();
Humanoid.WalkSpeed = 23
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
end
Sprinting = true;
end;
end);
game:GetService("UserInputService").InputEnded:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 70
}):Play();
Humanoid.WalkSpeed = 16
if Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
Sprinting = false;
end;
end);
InputBegan only fires once every time the player begins an input, same thing goes with InputEnded when the player stops interacting. When you hold shift, the script runs once and checks that you are not moving, and when you start moving, the script won’t run again to check if the player is still moving thus won’t play the animation. For InputEnded, when you hold shift and stop moving, input keycode isn’t left shift but instead w, a, s or d so the animation continues playing without being stopped.
The solution is to set up a Humanoid:GetPropertyChangedSignal(“MoveDirection”) inside InputBegan and play the animation when magnitude is greater than 0 and stop playing the animation when magnitude is equal 0, and disconnect the connection when InputEnded.
Check this if you are not familiar with the function: https://developer.roblox.com/en-us/api-reference/function/Instance/GetPropertyChangedSignal
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 80
}):Play();
Humanoid.WalkSpeed = 23
Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
elseif Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
end)
Sprinting = true;
end;
end);
but he said disconnect in Input ended but I dont know how?
game:GetService("UserInputService").InputEnded:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 70
}):Play();
Humanoid.WalkSpeed = 16
Sprinting = false;
end;
end);
Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
elseif Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
end)
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 80
}):Play();
Humanoid.WalkSpeed = 23
Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
elseif Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
end)
Sprinting = true;
end;
end);
but he said disconnect in Input ended but I dont know how?
game:GetService("UserInputService").InputEnded:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 70
}):Play();
Humanoid.WalkSpeed = 16
Sprinting = false;
end;
end);
Basically, GetPropertyChangedSignal creates a connection when the MoveDirection property changes, which means if you press shift twice, two connections will be created thus the animation will play and stop twice which might create bugs. How you disconnect connections is by assigning them to a variable and then call :Disconnect()
Example:
local connection = Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
--code here
end)
connection:Disconnect() --this stops the code inside the connection from running again
Create the connection inside InputBegan, disconnect the connection inside InputEnded. You can make the variable global by removing the “local” before it or create the variable at the top of the script, outside the connections and assign it to the connection.
local connection
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 80
}):Play();
Humanoid.WalkSpeed = 23
connection = Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
elseif Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
end)
Sprinting = true;
end;
end);
My bad. The connection wasn’t assigned properly. I just went into studio to check and apparently, you cannot call :Connect() on connections as variables like that.
What you do with this is:
local connection
connection = Humanoid:GetPropertyChangedSignal("MoveDirection")
connection:Connect(function()
--code
end)
connection:Disconnect()
Alright I know now. GetPropertyChangedSignal returns a RBXScriptSignal, RBXScriptSignal:Connection() returns a RBXScriptConnection, we will need 2 variables on that. This should work
local connection
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProccesed)
if (Input.KeyCode == Enum.KeyCode.LeftShift) and Parent:FindFirstChild("Humanoid") and Humanoid.Health > 0 and Humanoid.WalkSpeed ~= 0 and not gameProccesed then
TweenService:Create(workspace.CurrentCamera, TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut), {
FieldOfView = 80
}):Play();
Humanoid.WalkSpeed = 23
local signal = Humanoid:GetPropertyChangedSignal("MoveDirection")
connection = signal:Connect(function()
if Humanoid.MoveDirection.Magnitude > 0 then
Sprint:Play(.5)
elseif Humanoid.MoveDirection.Magnitude <= 0 then
Sprint:Stop(.25)
end
end)
Sprinting = true;
end;
end);
No, it has nothing to do with the magnitude being lower than 1 because it is an approximate value of MoveDirection. The animation is buggy because the InputBegan established multiple connections at once, so when the magnitude is greater than 0, many animations get played at the same time. If you disconnect the connection, it would maintain 1 connection at all times and only 1 animation should play at once.
Well, just make sure you don’t play another animation when an animation is already running. Roblox has a pretty nice function for this: Animator:GetPlayingAnimationTracks which returns all current playing animation tracks as an array so you can stop all of them.
Now that I realize, you loaded animation into Humanoid, though this still does work, is not recommended, as loading animations to Animator is much more efficient. An animator is always automatically created inside Humanoid when the character loads.