Loop causing lag

PROBLEM

Some people (about half, after conducting a vote.) have experienced an increase in lag at my development team’s game. With most of my developer’s, and contracted developer’s being different timezones; or just not available at this time. I am in need of some help from the DevForum community as I’m nearly brain dead after working on a huge texture revamp for my game for the past 8+ hours.

DEV CONSOLE:

A whopping 2,603,360 r/s - something I have never even seen from our game before. Which is quite strange with all the recent updates not being scripting related; let alone even closely relative to this specific script.

If anybody could point me in the right direction as the best way to completely avoid further issues in regards to this specific script, that would be amazing. Thanks!

SCRIPT (server sided)

game.Players.PlayerAdded:connect(function(plr)
	wait(5)
local Prison = "Really black"
local Visitor = "Flint"
local Default_Time = 500
local p = plr
local userId = p.userId
local stat = p:WaitForChild("leaderstats",100)
local pris = stat:WaitForChild("Prison Time",10)
local time = 0

wait (5)

coroutine.wrap(function()
	wait()
	while true do
		wait(1)
			if (time > 2) then
				for i,v in pairs(p.Character:GetChildren()) do
					if v:IsA("Tool") then
						v:Destroy()
					end
				end
				time = time - 1
				pris.Value = time
			elseif (time <= 2) and p.TeamColor == BrickColor.new(Prison) then
				wait(1)
				if (time <= 2) and p.TeamColor == BrickColor.new(Prison) then
				p.TeamColor = BrickColor.new(Visitor)
				pris.Value = 0
				time = 0
				game.StarterGui.Menu.Menu.Enabled = true
				p.Character.Humanoid.WalkSpeed = 0
				for a, obj in pairs(p.Character:GetChildren()) do 
					if obj:IsA("BasePart") then obj.Anchored = true end 
				end
				p:LoadCharacter()
		end end
	end
end)()

coroutine.wrap(function()
	wait()
	while wait() do
		if pris.Value > 2 and p.TeamColor ~= BrickColor.new(Prison) then
			p.TeamColor = BrickColor.new(Prison)
			time = pris.Value
		end
		
	end
	end)()
	
	coroutine.wrap(function()
		wait()
		while wait(10) do
			if pris.Value > 2 then
				p.PlayerGui:WaitForChild("Menu",10).Menu.Enabled = false
				wait(0.5)
				p.PlayerGui:WaitForChild("MirandaRights",10).Frame.Visible = true
				wait(0.5)
				p.PlayerGui:WaitForChild("MirandaRights",10).Frame["Time Left"].Script.Disabled = false
				wait(0.5)
				p.Backpack:ClearAllChildren()
				wait(0.5)
				p.Character:WaitForChild("Shirt",10).ShirtTemplate = "http://www.roblox.com/asset/?id=197908611"
				wait(0.5)
				p.Character:WaitForChild("Pants",10).PantsTemplate = "http://www.roblox.com/asset/?id=828218140"
				wait(0.5)
			end
		end
end) ()
p.Changed:connect(function()
	if p.TeamColor == BrickColor.new(Prison) then
		if pris.Value <= 2 then
			pris.Value = Default_Time
			time = pris.Value
			p:LoadCharacter()
		end
	end
	end)
	
	
game.ReplicatedStorage.bail.OnServerEvent:connect(function(ppp)
	if plr == ppp then
	--
	if game.ServerStorage.Data[ppp.Name.."Cash"].Value >= 5000 then
		game.ServerStorage.Data[ppp.Name.."Cash"].Value = game.ServerStorage.Data[ppp.Name.."Cash"].Value-5000
		ppp.leaderstats["Prison Time"].Value = 0
		time = 0
	end
	--
	end
end)

end)

You have a lot of coroutines that could be changed to operate as a single event.
Coroutines like this will continue to use memory when used on the server , even once the player leaves. You have to close them when they player leaves. (I wouldnt even bother using coroutines here)

The other thing is, one of your coroutines constantly spawns more coroutines, to put it simply, its bad news.

Like here, just wait for something to be added then check if its what your looking for.

This one has waits with no time in :roll_eyes: and only changes teamcolours.

3 Likes

Also:

You’re listening to any change on the player. You might even be making a change again with LoadCharacter.

Try Instance | Documentation - Roblox Creator Hub to listen to just changes in TeamColor and nothing else.

2 Likes

Certainly messy,

Essentially I could change most things in to functions and do

p.Changed:connect(function()
if pris.Value > 2 and p.TeamColor ~= BrickColor.new(Prison) then
		p.TeamColor = BrickColor.new(Prison)
end

if pris.Value > 2 and p.TeamColor == BrickColor.new(Prison) then

---- functions


elseif p.TeamColor == BrickColor.new(Prison) and pris.Value <= 2 then
		pris.Value = Default_Time
		time = pris.Value
		p:LoadCharacter()
	end
end
end)

and noted @nicemike40 - just seen that as I finished typing this out, and frankly too lazy to go back and replace what I already had typed with your suggestion. I appreciate that though, I’ve never even thought about that before!

Literally just replace

p.Changed:connect

with

p:GetPropertyChangedSignal("TeamColor"):Connect

I didn’t mention it just as a minor improvement :slight_smile: I think you genuinely might have indirectly made an infinite Changed loop that’s causing the crazy high rate.

1 Like

no, no, of course. I plan on implementing your idea. As said, I’m a bit brain dead as of this moment from hours in studio. I meant I was too lazy to edit my post’s example script with it haha.

I am definitely using that.

1 Like

It would be wise to take breaks, I find having a break gives me time to think without the need to put anything down, this is actually really helpful and has helped me come up with new methods by overthinking what the wording on the API really means (API wording is often overlooked due to the way they casually mention something)

Id say put together what everyone has said so far and then later on when you have a bit more experience go back to it and see what you can improve.

Question however, would:

stat:GetPropertyChangedSignal("Prison Time"):Connect

be more appropriate? As the script also checks & puts them on the Prisoner Team in case they have found a way off of the team - such as rejoining.

@MiniMachitoo I appreciate the advice! I’m definitely taking a break as soon as I finish patching this, as we average nearly 100 players among our recent updates. With our entire community experiencing this increase in lag, it is a potential loss in revenue, activity, etc.

I just realized why that would be a bad idea haha, hang on. I believe there is a saved value within the player that is “InJail.” and I was thinking of that for some reason.

So as for the InJail value, would it work in that sense better?

Maybe? It would be different functionally than what you currently have. Can’t really say without knowing what you’re trying to do. I’d guess “no”.

If they rejoin, then the Player object (and thus its leaderstats and Prison Time) are useless anyways.

Those save using a datastore, and is retrieved upon rejoining.

I mean, you’re the only one that’s changing InJail, so you don’t really need to listen for changes. You can just do whatever you want when you change it.

I’m not totally clear on the purpose of this script in the first place, so I can’t give you a ton of advice.

After a little bit of basically re-writing the entire script in order to make sure it doesn’t clog up any unneccessary usage on the server, and running tests to make sure it completely works, these are the results:

game.Players.PlayerAdded:connect(function(plr)
	wait(5)
local Prison = "Really black"
local Visitor = "Flint"
local Default_Time = 30
local p = plr
local userId = p.userId
local stat = p:WaitForChild("leaderstats",100)
local pris = stat:WaitForChild("Prison Time",10)
	local time = 0
	local injail = false

	wait (5)
	
	local function check()
		
		if pris.Value < 1 and p.TeamColor == BrickColor.new(Prison) then
			pris.Value = Default_Time
			time = pris.Value
			p:LoadCharacter()
			injail = true
		end
		
		if pris.Value > 2 and p.TeamColor ~= BrickColor.new(Prison) then
			p.TeamColor = BrickColor.new(Prison)
			time = pris.Value
			p.LoadCharacter()
		end
		

			
		if pris.Value > 2 and p.TeamColor == BrickColor.new(Prison) then
			
				injail = true
		
			end
			
			while injail do
				wait(1)
				
			time = time - 1
			
			pris.Value = time
			
			for i,v in pairs(p.Character:GetChildren()) do
				if v:IsA("Tool") then
					v:Destroy()
				end
			end
			
			p.Backpack:ClearAllChildren()
			
			if p.PlayerGui:WaitForChild("Menu",10).Menu.Enabled == true then
				p.PlayerGui:WaitForChild("Menu",10).Menu.Enabled = false
				end
			
			if p.PlayerGui:WaitForChild("MirandaRights",10).Frame.Visible == false then
				p.PlayerGui:WaitForChild("MirandaRights",10).Frame.Visible = true
				end
			
		if 	p.PlayerGui:WaitForChild("MirandaRights",10).Frame["Time Left"].Script.Disabled == true then

				p.PlayerGui:WaitForChild("MirandaRights",10).Frame["Time Left"].Script.Disabled = false 
				end

			if p.Character:WaitForChild("Shirt",10).ShirtTemplate ~= "http://www.roblox.com/asset/?id=197908611" then
				p.Character:WaitForChild("Shirt",10).ShirtTemplate = "http://www.roblox.com/asset/?id=197908611"
				end
			if p.Character:WaitForChild("Pants",10).PantsTemplate ~= "http://www.roblox.com/asset/?id=828218140" then
				p.Character:WaitForChild("Pants",10).PantsTemplate = "http://www.roblox.com/asset/?id=828218140"
			end
				
			if (time < 2) and p.TeamColor == BrickColor.new(Prison) then
				injail = false
				p.TeamColor = BrickColor.new(Visitor)
				time = 0
					pris.Value = 0
				game.StarterGui.Menu.Menu.Enabled = true
					p:LoadCharacter()
				end
				
			end
	
		end
	
	
	p:GetPropertyChangedSignal("TeamColor"):Connect(check)
	
game.ReplicatedStorage.bail.OnServerEvent:connect(function(ppp)
	if plr == ppp then
	--
	if game.ServerStorage.Data[ppp.Name.."Cash"].Value >= 5000 then
		game.ServerStorage.Data[ppp.Name.."Cash"].Value = game.ServerStorage.Data[ppp.Name.."Cash"].Value-5000
		ppp.leaderstats["Prison Time"].Value = 5
		time = 5
	end
	--
	end
end)

end)

Thanks to everybody who gave advice in regards to the most efficient way of approaching this solution!

I mean, you still have an infinite changed loop there, but whatever if it works for you great I suppose lol