Hello, I am making a stamina system for my fighting game.
I have a few problems with it though,
It causes lots of lag
It causes a client-sided memory leak
I need to optimize my code to be more efficient.
Basically how my system is set out is that there’s a ModuleScript that is accessible by _G from the client. The Module has a few functions which include:
Functions in the Module
local MaxStamina = 100
local Stamina = MaxStamina
local StaminaChanged = script:FindFirstChild("StaminaChanged") -- This is a BindableEvent, btw
function module:IncrementStamina(Integer)
if Integer ~= nil then
if typeof(Integer) == 'number' then
Stamina = math.clamp(Stamina + Integer, 0, MaxStamina)
StaminaChanged:Fire(Stamina)
end
end
end
function module:SetStamina(Integer)
if Integer ~= nil then
if typeof(Integer) == 'number' then
Stamina = Integer
StaminaChanged:Fire(Stamina)
end
end
end
function module:GetStamina()
return {Stamina, MaxStamina}
end
And then there’s a LocalScript that controls the regeneration.
local PlayerModule = _G.PlayerModule
local StaminaChanged = PlayerModule:WaitForChild("StaminaChanged", 0.1)
PlayerModule = require(PlayerModule)
local MaxStamina = PlayerModule:GetStamina()[2]
local LastStamina = PlayerModule:GetStamina()[1]
local RegenStartTime = 2 -- Time to wait before starting the regeneration
local Incrementing = false
StaminaChanged.Event:Connect(function(NewStamina)
if NewStamina < LastStamina then
if Incrementing == true then
Incrementing = false
end
end
spawn(function()
wait(RegenStartTime)
if PlayerModule:GetStamina()[1] == NewStamina then
Incrementing = true
while Incrementing == true do
if PlayerModule:GetStamina()[1] ~= MaxStamina then
PlayerModule:IncrementStamina(0.1)
else
Incrementing = false
break
end
wait()
end
end
end)
LastStamina = NewStamina
end)
The scripts that deduct stamina also work similarly to this as well, they utilize while loops that run while conditions are met and then they eventually stop when those conditions are different.
I need urgent help because I’m planning to optimize my game as much as possible.
Thank you.
StaminaChanged.Event:Connect(function(NewStamina)
if not Incrementing then
return
end
You should probably do this, otherwise the event could be fired multiple times resulting in the execution of multiple spawn tasks which are calling multiple functions every frame.
Remove spawn(function() since Events start new threads automatically so its not needed and you’re just stacking another thread where one isn’t needed.
Instead of a while loop you should try using RunService.RenderStepped/RunService.PostSimulation.
Also use task.wait() its better than normal wait() and when passed without arguments has a 2x lower wait time since it acts like RunService.Heartbeat:Wait(). (wait is .03 which is 2 frames and task.wait is .015 which is a single frame)
I wouldn’t recommend to use global variables as they’re not encouraged to be used in new works.
I recommend you to use the task library instead of using these legacy functions to yield and spawn threads.
I also wouldn’t try to spawn threads to handle the stamina regeneration because it’s going to eat a lot of memory, plus your threads would NEVER die or garbage collected because there is a continuos while loop in it.
No. RenderStepped shouldn’t be used if the code doesn’t involve the camera. Use RunService.Heartbeat instead.
Also, task.wait() isn’t the same as RunService.Heartbeat:Wait() as RunService Heartbeat returns the amount of seconds elapsed since the previous heartbeat(physics simulation) is done while task’s wait returns the number of seconds elapsed since the last call of this function.