Hello! I’ve recently made a projectile system, it’s pretty good surface level and I’m happy with it, but there are some optimization issues.
When more than around 10 active projectiles are in flight, occasional lag spikes will occur, and after around 80 projectiles, consistent lag will occur, with intense lag spikes. Looking at the micro-profiler, as is expected, the projectile system is causing lag, but only the consistent lag, not the lag spikes. The job causing the lag spikes goes by the name, “deleteDeferred.” I don’t know what this means or how to optimize this particular job, so I’m kind of stuck.
I’m not too worried about the consistent lag caused by my projectile system, I know I can easily optimize that, but I am concerned about the lag spikes and, “deleteDeferred.” I can’t really find anything on what this job is, so I started guessing.
I assumed maybe this had something to do with the Garbage Collector deleting deferred events, so I tried to change SignalBehavior under Workspace to Immediate, which didn’t solve the issue.
I then guessed that it might be because there were too many RenderStepped connections caused by adding projectiles, so I swapped it from RenderStepped to BindToRenderStep, which did not work either.
I can’t really include all the code in the module that handles each individual projectile, but I can send the main function that actually does the casting
function meta:Cast(dt:number)
self:DeltaTimeSetup(dt) -- Synchronizes the delta time for other functions, ease of access
self.CurrentRoot = self.CurrentEnd -- Root moves to the previous frames End
self.CurrentEnd = self.CurrentEnd + (self.Velocity * self.deltaTime) + (0.5 * self.Acceleration * self.deltaTime^2) -- End moves via the equation x=x0+V0t+0.5at^2
local drag = self:Aerodynamics(self.DragCoefficient) -- will auto disable itself if there is no drag coefficient, or drag is 0
self.Velocity += (self.Acceleration - drag) * self.deltaTime -- V = V0 + at
self.Age += self.deltaTime
---- RAYCASTING STARTS HERE
if self.VisualizeDebug then
self:VisualizeDebg(self.CurrentEnd, 1)
else
self:Visualize(self.CurrentEnd)
end
local params = RaycastParams.new()
params.FilterType = self.Params.FilterType
params.FilterDescendantsInstances = self.Params.FilterDescendants
self.RayResult = workspace:Raycast(self.CurrentRoot, self.CurrentEnd - self.CurrentRoot, params)
-- Terminating the ray, or penetrating --
if self.RayResult then
self:PenCheck() -- Checks if the projectile can penetrate
SafeFunc(self.Params.OnStrikeFunc, self) -- SafeFunc just avoids errors if a function doesn't exist
elseif self.Age >= self.Lifetime then -- The projectile is too old
self:Terminate()
else
SafeFunc(self.Params.OnRunFunc, self)
end
-- Terminating the ray, or penetrating --
self.firstFrameDebounce = true
end