Why is my game lagging?

I programmed my game from the beginning in a manner to avoid memory leaks and overall lag. Since it’s physics heavy and a ship battle game (as you can see in the background), I expected some lag occasionally.
However, due to my precautions, and my “smart” garbage collector script that clears ships that have not been interacted with for some time, it runs smoothly… for the first 30-40 minutes of the server running.

Issue: The issue is after that amount of time goes by it goes completely downhill and my game starts to lag, the .Touch() events on the cannonballs react late and thus bounce off ships and blow up in the water. This was cause for a lot of people disliking the game which unfortunately isn’t warranted, but I digress. People don’t understand the struggle… :pensive:

Notice: I attached a picture of the dev console’s PlaceMemory in the laggy server and literally everything is perfect, only using ~110 MB, but for some reason the actual game is laggy?

Question: Does anyone have any idea on how to resolve this or if I’m looking in the wrong place?

PS. all ship movement controller stuff is handled on the server.

2 Likes

Are you disconnecting connections after they’re not needed anymore?

1 Like

There appears to be only one issue here. That issue being the gradual pile up of memory connections causing memory leaks. There are different types of leaks. As we can see here, PhysicsParts seems to take up over 50% of your place memory. If I am not mistaken, touch-sensitive connections go under PhysicsParts.

4 Likes

Yes, I used the DebrisService on all my cannon balls on top of :Destroy()'ing the part once it does eventually detect a part touched (hence why my memory is reasonably low). Notice how Signals only uses 10 MB.

1 Like

You still have to :Disconnect() the Touch connection.

1 Like

DebrisService doesn’t disconnect .Touched connections, all it does it destroy baseparts (correct me if im wrong), you need to store the connections and then call :Disconnect() on them!
I recommend using Maids, in my round based game I’m working on, almost everything is given to a maid which is destroyed at the end of the round! https://github.com/Quenty/NevermoreEngine/blob/a8a2d2c1ffcf6288ec8d66f65cea593061ba2cf0/Modules/Shared/Events/Maid.lua

1 Like

I had a feeling that was the issue, but then I found this little snippet in the API Reference:

Always call Disconnect() when a connection is no longer needed. Forgetting to do so can cause your game to use more resources than necessary. Note, however, that this may not always be necessary; when an object is destroyed, all connections to that object’s events are disconnected automatically.

And since I am indeed destroying the instance I assumed all connections to the part were to be disconnected automatically – unless I misinterpreted what an object is in this situation.

I checked it out, it’s pretty cool but it seems to clean everything at once, so it would fit a rounds based game nicely, my game is more dynamic and cannonballs should get disconnected/destroyed after 2 seconds, hence why I used the DebrisService.

Although from what I read, they do get disconnected automatically, I will try make them disconnect prior to getting destroyed.

There is no need if you destroy them, are you creating any instances within the connection?

Yes. Initally I was going to say no but I have another function inside that does quite a bit of work, here’s a snippet from my FireCannon() function:

function FireCannon(Player, Cannon)
  -- Code...
		spawn(function()
			Shot.Touched:Connect(function(Part)
				Shot.Anchored = true
				if Shot.Position.Y < 60 then
					SpawnExplosion(Player, Vector3.new(Shot.Position.X, 60+5, Shot.Position.Z), 1)
				else
					SpawnExplosion(Player, Shot.Position, 1)
				end
				Shot:Destroy()
			end)
		end)
  -- Code...
end)

and here’s my entire SpawnExplosion() function:

function SpawnExplosion(Player, Position, Size)
spawn(function()
	-- Detection
	local sphere = Instance.new("Part")
	sphere.Shape =  Enum.PartType.Ball
	sphere.Anchored = true
	sphere.Position = Position
	sphere.Transparency = 1
	sphere.CanCollide = false
	sphere.Size = Vector3.new((ExplosionRadius*5)*Size, (ExplosionRadius*5)*Size, (ExplosionRadius*5)*Size)
	sphere.Parent = workspace
	
	local impactedParts = utilitiesLibrary.GetTouchingParts(sphere)
	local impactedPlayers = {}
	for i = 1, #impactedParts do
		if impactedParts[i].Anchored == false and (sphere.Position - impactedParts[i].Position).magnitude > ExplosionRadius*Size then
			utilitiesLibrary.SpawnSound("ImpactSound", impactedParts[i])
			spawn(function()
				local lastColor = impactedParts[i].Color
				impactedParts[i].Color = Color3.fromRGB(255, 255, 255)
				
				local goal = {}
				goal.Color = lastColor
				local tweenInfo = TweenInfo.new(1)
				local tween = TweenService:Create(impactedParts[i], tweenInfo, goal)
				tween:Play()
			end)
		else
			local impactedPlayer = game.Players:GetPlayerFromCharacter(impactedParts[i].Parent)
			if impactedPlayer and not table.find(impactedPlayers, impactedPlayer) then
				table.insert(impactedPlayers, impactedPlayer)
				RemoteEvents.CameraShakeEvent:FireClient(impactedPlayer)

				TagCharacter(Player, impactedPlayer, "Explosion")
			end
		end
	end

	-- Clean
	sphere:Destroy()
	
	wait(.05)
	
	-- Explosion
	local explosion = Instance.new("Explosion")
	explosion.BlastRadius = ExplosionRadius*Size
	explosion.BlastPressure = ExplosionForce*Size -- these are really wussy units
	explosion.Position = Position
	explosion.Parent = game.Workspace

end)

Although the instances I do create all get destroyed eventually too. Does the connection still persist in memory even though the cannonball gets destroyed because of the SpawnExplosion() function? If so, that would actually be a cause of lag.

This is not related to your issue I think but do not use spawn here is the reason why: Coroutines V.S. Spawn()... Which one should I use? - #10 by buildthomas.

Have you tried taking a few server microprofillers and seeing if anything is taking awhile to process?

I think using explosions on the server itself can cause the game to lag, also explosions automatically destroy the character according to the devhub.

Thanks, I checked it out and found it useful, ill go around to update my code with this in mind later once I solve this issue.

Didn’t think about that, I will do so next time I find a laggy server, cheers.

How about object pooling parts/projectiles instead of destroying them each time? That might help lessen the strain on the server.

I was thinking of caching parts but i already have a 1 shot / 10 seconds on each cannon and I found there to be no use logistically, the impact would be negligible as I’m not spawning say 10 shots per 1 second.

1 Like

Sorry this has still been on my mind since yesterday, so I did some testing and it seems like it does. Can somebody confirm this or provide some sources to the contrary?

It will destroy the connection if the you call the method AddItem on the part with the touched connection because that method Destroys the part after the specified time, remember that destroying an instance will disconnect all the connections on that instance.

1 Like