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…
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?
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.
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.
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.
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.
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.
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.