Closed Headshotz closed 4 years ago
Maybe do not create a new emitter every frame?
Would this be a duplicate of https://github.com/Facepunch/garrysmod-issues/issues/1968 ?
I don't think this is a duplicate. Usually when this happens there isn't a LinkedListOverflow, it's mostly just all new effects being created are NULL. I don't think that's supposed to happen - either create an effect entity with a valid table, or don't create anything at all.
Usually once this error occurs it quickly progresses to breaking all map rendering and then crashing the client.
It also appears that whenever the issue occurs, a full GMod restart is needed to recover, map changes won't fix it and sometimes it becomes so bad that there's just a black screen on the next map, but players can still move and interact.
I managed to get these console messages but nothing breaks? It's really hard to understand what the OP is saying, what actually breaks, where is 2048 number comes from, etc.
[ERROR] ParticleEmitter: Couldn't make emitter! Too many emitters!
ParticleEmitter limit is 4096. Hitting this doesn't cause any issues, as soon as there's a free slot, it all starts to work again.
Render queue too large, flushing! (This is super slow you shouldn't render so much stuff.)
Also seen this, but again it doesn't do much in terms of things breaking.
Couldn't make effect 'tracer_actinic' - Too many Lua Effects (2049)! Are you killing them properly? (x20)
WARNING: Broke possible Lua Effect infinite loop! Check your code!
Also seen this, which again doesn't cause any problems on its own for me, even when server is close to/at the edict limit, as soon as enough effects get free'd other effects can spawn again as normal.
This was tested in local MP on flatgrass. I didn't use 100 bots, I just used 100 bullet per shot weapon_base, as I couldn't make anything happen with a bunch of bots.
To me, your particle effect code is trash. Here's a slightly edited version that doesn't create a new emitter for every single particle, i.e. this is how you are actually supposed to use particle emitters:
function EFFECT:Init( data )
self.Position = data:GetStart()
self.WeaponEnt = data:GetEntity()
self.Attachment = data:GetAttachment()
self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment )
self.EndPos = data:GetOrigin()
self.Life = 0
self:SetRenderBoundsWS( self.StartPos, self.EndPos )
self.Emitter = ParticleEmitter(self.EndPos)
end
function EFFECT:Think( )
self.Life = self.Life + FrameTime() * 10 -- Effect should dissipate before the next one.
self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment )
return self.Life < 1
end
local beammat = Material("trails/smoke")
local glowmat = Material("sprites/light_glow02_add")
function EFFECT:Render()
local texcoord = math.Rand( 0, 1 )
local norm = (self.StartPos - self.EndPos) * self.Life
local dir = (self.StartPos - self.EndPos):Angle()
local dfwd = dir:Forward()
local dup = dir:Up()
local drgt = dir:Right()
local nlen = norm:Length()
local prevspinpos = self.StartPos
local alpha = 1 - self.Life
if ( self.Emitter ) then
self.Emitter:SetNearClip(24, 32)
local particle = self.Emitter:Add("effects/blueflare"..math.random(1, 1), self.EndPos - (self.EndPos - self.StartPos) * math.Rand(0, 1))
local vel = VectorRand():GetNormal() * 25
particle:SetDieTime(1)
particle:SetColor(255,45,45)
particle:SetColor(255,45,45)
particle:SetStartAlpha(125)
particle:SetEndAlpha(0)
particle:SetStartSize(2)
particle:SetEndSize(0)
particle:SetVelocity(vel)
particle:SetGravity(vel * -0.5)
particle:SetRoll(math.random(360))
end
render.SetMaterial(beammat)
for i = 0, nlen, 32 do
if i > 704 then break end -- Limit the range on the spin beam effect...otherwise might be expensive.
local set = i - CurTime() * 15
local basebeampos = self.StartPos - dfwd * i
local spinbeampos = basebeampos + dup * math.sin(set) * 6 + drgt * math.cos(set) * 6
if i == 704 then spinbeampos = basebeampos end -- Tie the spin back into the main beam at the end of the spin beams
render.DrawBeam(prevspinpos, spinbeampos, 3, texcoord + i, texcoord + nlen / 128 + i, Color(255, 0, 0, 255 * alpha))
prevspinpos = spinbeampos
end
for i = 0, 4 do
render.DrawBeam(self.StartPos, self.EndPos, 2.3, texcoord, texcoord + nlen / 128, Color(145, 45, 45, 200 * alpha))
end
render.DrawBeam(self.StartPos, self.EndPos, 8.5, texcoord, texcoord + nlen / 128, Color(255, 15, 15, 255 * alpha))
render.SetMaterial(glowmat)
render.DrawSprite(self.StartPos, 50, 50, Color(255, 0, 0, 200 * alpha))
render.DrawSprite(self.EndPos, 50, 50, Color(255, 25, 25, 148 * alpha))
end
Wouldn't that new code actually cause a leak? I can't see finish being called from anywhere in there.
You are not obligated to call it. It will be automatically GC'd after the effect entity gets deleted (i.e. no more references) and when all particles are dead.
You can test this yourself.
Edit: if you really want to, you can call Finish()
just before returning in EFFECT:Think
when self.Life >= 1
function EFFECT:Think( )
self.Life = self.Life + FrameTime() * 10 -- Effect should dissipate before the next one.
self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment )
local isAlive = self.Life < 1
if ( !isAlive && self.Emitter ) then self.Emitter:Finish() end
return isAlive
end
Interesting. The wiki says that you must call Finish when you're done with the emitter, but if that's not the case that's a lot better. I just remember all these issues with particle emitters from years ago.
The sandbox gamemode itself can create this form of misbehaviour The tool tracer sometimes creates infinite particles, thus breaking all particles all together, because they are all null.
Can you take like a few minutes and properly explain what the issue is? Actually make sense?
The sandbox toolgun tracer doesn't even use particles at all. https://github.com/Facepunch/garrysmod/blob/master/garrysmod/gamemodes/sandbox/entities/effects/selection_ring.lua https://github.com/Facepunch/garrysmod/blob/master/garrysmod/gamemodes/sandbox/entities/effects/selection_indicator.lua https://github.com/Facepunch/garrysmod/blob/master/garrysmod/gamemodes/base/entities/effects/tooltracer.lua
Having too many particles doesn't really cause any issues, they just will not get created until there's a slot, Lua will get a fake particle.
So what is the actual problem here? Is there even one?
Im om vacation right now. I can get you a stack trace of the problem when im home. I actually have These in older files
I've done some further investigation. At least on my end, the issue was caused by a slow ClientsideModel leak. Since effects and ClientsideModels share NonNetworkedEntity slots, leaking clientside models will eventually cause the behavior. I would not consider this a new bug. Sorry about that.
Thanks. So I am guessing the biggest issue here is that the created effect entity has self
as NULL
. Not much I can do about addons leaking ClientsideModels.
And that should be fixed on Dev. I did not observe any crashes in my testing, Don't know if there's anything else to be done here, so I am going to close this. Still don't know where particles come into play here but whatever.
As far as I can tell this is largely an issue with your Lua code, but if you can find anything else that causes big issues when hitting the limit, feel free to share, but please with proper steps to reproduce, or at least a good explanation of what the issue is.
Details
After reached at 2048 particle limit can be cause its break the Clientside Model that become a NULL, I don't have idea why its does NULL. Also, its not clean the lua particle effects after map change when particles limit were full.
Steps to reproduce
You need 100 bots and force them to firing gun with custom lua effect that file I uploaded.
File: tracer_actinic.zip