I have this part of my script which for every second adds one to the seconds’ value. Every second it goes through all the players and adds 1. It works fine with one player but with two or more players, one of them might be going up by two(the others’ might not even go up) and it starts randomly going up by one, two etc.
The part:
RunService.Heartbeat:Connect(function()
if not (tick() >= NextStep) then return false end
NextStep = NextStep + 1
local Plrs = Players:GetChildren()
for index = 1, #Plrs do
Player.leaderstats.Seconds.Value += 1
end
end)
The whole script:
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local HttpService = game:GetService("HttpService")
local RunService = game:GetService("RunService")
local checkpoints = workspace.Checkpoints
local ga = false
local NextStep = tick()
Players.PlayerAdded:Connect(function(Player)
local PlayerDataStore = DataStoreService:GetDataStore("PlayerStore", Player.UserId)
warn("Initializing leaderstats...")
local stats = Instance.new("Folder")
stats.Name = "leaderstats"
stats.Parent = Player
local wipeouts = Instance.new("IntValue")
wipeouts.Name = "Deaths"
wipeouts.Parent = stats
local second = Instance.new("IntValue")
second.Name = "Seconds"
second.Parent = stats
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Parent = stats
print("Completed.")
warn("Initializing leaderstats values...")
local success = PlayerDataStore:GetAsync("success")
local PlayerData = PlayerDataStore:GetAsync("PlayerData")
if success == nil or false then
print("Player is currently nil")
PlayerDataStore:SetAsync("success", true)
PlayerDataStore:SetAsync("PlayerData", HttpService:JSONEncode({deaths = 0, sec = 0, stages = 0}))
Player:Kick("Rejoin, you have no data")
elseif success == true then
local decoded = HttpService:JSONDecode(PlayerData)
--for k,v in pairs(decoded) do
--print(k, v, type(v))
--end
Player.leaderstats.Deaths.Value = decoded.deaths
Player.leaderstats.Seconds.Value = decoded.sec
Player.leaderstats.Stage.Value = decoded.stages
print(success)
print("Completed.")
warn("Continuing with normal RunTime")
Player.CharacterAdded:connect(function(Character)
local humpart = Character.HumanoidRootPart
RunService.Stepped:wait()
humpart.CFrame = checkpoints[stage.Value].CFrame+ Vector3.new(0,math.rad(3.5),0)
local d = true
Character:WaitForChild("Humanoid").Died:Connect(function()
RunService.Stepped:wait()
humpart.CFrame = checkpoints[stage.Value].CFrame + Vector3.new(0,math.rad(3.5),0)
if d then
Player.leaderstats.Deaths.Value += 1
end
end)
RunService.Heartbeat:Connect(function()
if not (tick() >= NextStep) then return false end
NextStep = NextStep + 1
local Plrs = Players:GetChildren()
for index = 1, #Plrs do
Player.leaderstats.Seconds.Value += 1
end
end)
end)
end
end)
Players.PlayerRemoving:Connect(function(Player)
ga = true
local PlayerDataStore = DataStoreService:GetDataStore("PlayerStore", Player.UserId)
warn(string.format("%s IN QUEUE...", Player.Name:upper()))
local death = Player.leaderstats.Deaths.Value
local secs = Player.leaderstats.Seconds.Value
local stagess = Player.leaderstats.Stage.Value
local data = {deaths = death,sec = secs, stages =stagess }
local encoded = HttpService:JSONEncode(data)
PlayerDataStore:SetAsync("PlayerData", encoded)
print("Done")
end)
I just put how to do that. Replace tick() with one of the two options. Also are you using luau? Otherwise the += will fail.
local NextStep = os.time()
-- later on, NOT inside the PlayerAdded connection:
RunService.Heartbeat:Connect(function()
if not (os.time() > NextStep) then return false end
local diff = os.time() - NextStep
NextStep = os.time()
local Plrs = Players:GetChildren()
for index = 1, #Plrs do
if Plrs[index]:FindFirstChild('leaderstats') then
Plrs[index].leaderstats.Seconds.Value += diff
end
end
end)
Don’t do it from the client, you’ll get all of the second going up at slightly different times, plus people can exploit and send you a tonne of events to boost their stats.
There is not going to be any lag from 1 heartbeat connection on the server that does such a minimal task.
remote = -- remote event goes here
t = 0
RunService.Heartbeat:Connect(function(step)
t += step
if not (t > NextStep) then return false end
NextStep = NextStep + 1
remote:FireServer()
t = 0
end)
Server Script:
remote.OnServerEvent:Connect(function(player)
-- change player values here
end)
local Event = game:GetService('ReplicatedStorage').Event
Event.OnServerEvent:Connect(function(Player, ...)
-- You should probably check how many seconds has passed since the last :FireServer().
-- It would be needed as exploiters can do FireServer() with any arguments.
end)
-- Client
local Event = game:GetService('ReplicatedStorage'):WaitForChild('Event')
-- Your code
Event:FireServer()
And, for the waiting part:
local StartTime = tick()
wait(1)
local EndTime = tick()
print(EndTime - StartTime)
Based off of that, looping through every player and checking that often might cause some lag issues.
Performance-wise, I believe the client should handle the HeartBeat event, and let the server know afterwards.
Looping through every player in a heartbeat event to simply add a value will not lag.
At the very least test it before making claims and overcomplicating things for a beginner scripter and putting ideas into their head that extremely short and quick Heartbeat connections are bad. They aren’t if you use them properly. 59 of the 60 frames it won’t run anything beyond the first inequality anyway.
One of the benefits of using Heartbeat is that it doesn’t delay physics (or rendering if on the client) so even if it does run over once per second it’s not the end of the world. But it won’t.