So, i have this function connected via Left Shift. It activates every time you press that key. If you rapidly press or release Left Shift, not sprinting will regenerate more stamina and sprinting will wear off stamina faster, accordingly, until you stop pressing or releasing the button rapidly.
I haven't been able to solve this predicament to date, although i do have a clue: The sprinting value appears to be true or false when the loop is to check the conditions, depending on what you do rapidly. Even adding debounce didn't help.
Here's the script, with added comments:
local function Sprint(_,state) if state == Enum.UserInputState.Begin then --Sprint if script.Parent.Stamina.Value < 15 then return end --Minimum stamina needed game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 29 script.Parent.Sprinting.Value = true --Sprinting script.Parent.Stamina.Value = script.Parent.Stamina.Value - 3 while script.Parent.Stamina.Value > 0 and script.Parent.Sprinting.Value do --Drain stamina script.Parent.Stamina.Value = script.Parent.Stamina.Value - 1 wait(0.15) end else --Stop sprinting (releasing left shift) game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 12 script.Parent.Sprinting.Value = false --Not sprinting wait(1) while script.Parent.Stamina.Value <= 100 and not script.Parent.Sprinting.Value do --Regen stamina wait(0.5) script.Parent.Stamina.Value = script.Parent.Stamina.Value + 1 end end end game.ContextActionService:BindAction("Sprint", Sprint, false, Enum.KeyCode.LeftShift)
It can be dangerous and confusing to start loops inside events. It usually much simpler for events to simply direct the behavior of loops. The problem with your current design is that the same action (or different action) are allowed to be happening at the same time. It's sort of tedious to stop this from happening.
There's a cleaner way to write this sort of behavior.
I'll be writing using variables instead of _Value objects, because it's briefer. If you have multiple scripts looking at these values, though, you'd have to switch it back.
This is a much simpler way to write what you want -- there's only ever one thing happening at a time (instead of many, one for each keypress):
local sprinting = false -- Initially, you don't start running local stamina = 100 -- Initially, you start with full stamina local function Sprint(_, state) -- Begin or end sprinting: sprinting = state == Enum.UserInputState.Begin end game.ContextActionService:BindAction("Sprint", Sprint, false, Enum.KeyCode.LeftShift) while true do local dt = wait(0.15) -- Record ACTUAL time that has elapsed -- (instead of hoping it's actually .15, which it may not be) local humanoid = game.Players.LocalPlayer.Character.Humanoid if sprinting and stamina > 1 then humanoid.WalkSpeed = 29 -- (run) stamina = math.max(0, stamina - dt * 20/30) -- drain, down to 0 else sprinting = false -- (stop sprinting if you're out of energy)) humanoid.WalkSpeed = 12 -- (walk) stamina = math.min(stamina + dt * 2, 100) -- regenerate, up to 100 end end