Keep the sprinting system responsive and quick while also preventing the loops from stacking
Spamming the sprint button will cause more than 1 stamina to be taken away and way quicker than it should be, a sign that my loops are running multiple at a time
2. FunctionStacking
De-bounce (Made the responsiveness too slow and just didn’t work, might not have used it right not sure)
--// Services
local rs = game:GetService("ReplicatedStorage")
local uis = game:GetService("UserInputService")
local tweenservice = game:GetService("TweenService")
--// Stamina Module
local staminamodule = rs.Framework:WaitForChild("StaminaHandler")
local staminahandler = require(staminamodule)
--// Player Attributes
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local cam = workspace.CurrentCamera
--// Attributes [Stamina]
local Stamina = char:SetAttribute("Stamina", math.clamp(100, 0, 100))
--// Debounce i think dunno
local IsSprinting = char:SetAttribute("IsSprinting", false)
--// Tweening
local info = TweenInfo.new(0.2, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false)
local tweenout = tweenservice:Create(cam, info, {FieldOfView = 80})
local tweenin = tweenservice:Create(cam, info, {FieldOfView = 70})
--// Function
local function SprintEnd(input, _gameProcessed)
if input.KeyCode == Enum.KeyCode.LeftShift then
if (char:GetAttribute("IsSprinting") == true) then
char:SetAttribute("IsSprinting", false)
humanoid.WalkSpeed = 12
tweenin:Play()
while (char:GetAttribute("IsSprinting") == false) do
if (char:GetAttribute("IsSprinting") == false) then
if not (char:GetAttribute("Stamina") >= 100) then
task.wait(0.35)
staminahandler:Add(1)
else
print("Won't add, at full stamina")
return
end
end
end
end
end
end
local function SprintRequest(input, _gameProcessed)
if humanoid.MoveDirection.Magnitude > 0 then
if input.KeyCode == Enum.KeyCode.LeftShift then
char:SetAttribute("IsSprinting", true)
humanoid.WalkSpeed = 18
tweenout:Play()
while (char:GetAttribute("IsSprinting") == true) do
if (char:GetAttribute("IsSprinting") == true) then
if not (char:GetAttribute("Stamina") <= 0) then
task.wait(0.1)
staminahandler:Remove(1)
else
SprintEnd(input, _gameProcessed)
print("Exhausted!")
return
end
end
end
end
end
end
uis.InputBegan:Connect(SprintRequest)
uis.InputEnded:Connect(SprintEnd)
I honestly don’t know why they stack (so it’s a bit of a shot in the dark), however maybe combining the sprint function will remove the stacking from occouring.
I have my sprint script like this:
function startSprint()
sprinting = true
end
function stopSprint()
sprinting = false
end
function checkKey(key, isTyping, doSprint)
if not isTyping then
if key.KeyCode == sprintKey then
if doSprint then
startSprint()
else
stopSprint()
end
end
end
end
uis.InputBegan:Connect(function(key, isTyping)
checkKey(key, isTyping, true)
end)
uis.InputEnded:Connect(function(key, isTyping)
checkKey(key, isTyping, false)
end)
game:GetService("RunService").Stepped:Connect(function()
if sprinting then
if stamina > 0 then
if 1 == 1 then
if uis:IsKeyDown(Enum.KeyCode.W) or uis:IsKeyDown(Enum.KeyCode.S) or uis:IsKeyDown(Enum.KeyCode.A) or uis:IsKeyDown(Enum.KeyCode.D) then
if char.HumanoidRootPart.AssemblyLinearVelocity.Magnitude > 0.5 then
if game.Workspace.CurrentCamera.CameraType == Enum.CameraType.Custom then
stamina -= 0.02
humanoid.WalkSpeed = sprintSpeed
stamDecrease:FireServer(stamina)
end
end
end
end
else
humanoid.WalkSpeed = regularSpeed
end
else
if stamina < maxStamina then
stamina += maxStamina/500
stamIncrease:FireServer(stamina)
end
if game.Workspace.CurrentCamera.CameraType == Enum.CameraType.Custom then
humanoid.WalkSpeed = regularSpeed
end
end
if stamina < maxStamina then
plr.PlayerGui.Interface.bg.Bar:TweenSize(UDim2.new(stamina / maxStamina, 0, -1, 0), Enum.EasingDirection.In, Enum.EasingStyle.Linear, 0)
end
end)
Problem with this is that because the function that removes or adds stamina is connected to run service, it will always be checking the stamina every step, which afaik has a toll on performance
I took a slightly different approach to this, separated the stamina handling into a singular while loop and an excruciatingly basic function for the sprint toggle purely out of logic and untested. I’m completely unsure if this is what you’re trying to achieve and if it will be compatible with the rest of your dependencies, but give it a shot:
--// Services
local rs = game:GetService("ReplicatedStorage")
local uis = game:GetService("UserInputService")
local tweenservice = game:GetService("TweenService")
--// Stamina Module
local staminamodule = rs.Framework:WaitForChild("StaminaHandler")
local staminahandler = require(staminamodule)
--// Player Attributes
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local cam = workspace.CurrentCamera
--// Attributes [Stamina]
local Stamina = char:SetAttribute("Stamina", math.clamp(100, 0, 100))
--// Debounce i think dunno
local IsSprinting = char:SetAttribute("IsSprinting", false)
local KeyDown = false -- Control variable to store the current status of the sprint key
--// Tweening
local info = TweenInfo.new(0.2, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false)
local tweenout = tweenservice:Create(cam, info, {FieldOfView = 80})
local tweenin = tweenservice:Create(cam, info, {FieldOfView = 70})
--// Function
local function Sprint(status)
if status then
char:SetAttribute("IsSprinting", status)
humanoid.WalkSpeed = 18
tweenout:Play()
else
if (char:GetAttribute("IsSprinting") == true) then
char:SetAttribute("IsSprinting", status)
humanoid.WalkSpeed = 12
tweenin:Play()
end
end
end
uis.InputBegan:Connect(function(input, _gameProcessed)
if humanoid.MoveDirection.Magnitude > 0 then
if input.KeyCode == Enum.KeyCode.LeftShift then
KeyDown = true
Sprint(true)
end
end
end)
uis.InputEnded:Connect(function(input, _gameProcessed)
if input.KeyCode == Enum.KeyCode.LeftShift then
KeyDown = false
Sprint(false)
end
end)
while task.wait() do
if (char:GetAttribute("IsSprinting") == true) then
if not (char:GetAttribute("Stamina") <= 0) then
task.wait(0.1)
staminahandler:Remove(1)
else
Sprint(false)
print("Exhausted!")
end
elseif (char:GetAttribute("IsSprinting") == false) then
if not (char:GetAttribute("Stamina") >= 100) then
task.wait(0.35)
staminahandler:Add(1)
if KeyDown and (char:GetAttribute("Stamina") >= 20) then -- Continue the sprint once stamina has recharged upto 20
Sprint(true)
print("Running again!")
end
end
end
end