I am not sure what is causing lag in this situation

I was messing around with particle physics like Primordial Particle Systems and I tried it in roblox to see if it would work. Once I wrote everything and tried it out with upwards of 100 particles it began to lag and slow down a lot. I suspected this may be caused by the amount of touch events firing in the two hemispheres that are surrounding the particles. But I am also now unsure if it is the while loops that are running which is updating the particle’s rotation and position. In the videos I have seen of this type of simulation, they seem to run fine with over 500 particles. This may be because of the language it is running (possibly?). I am also not sure if it could be anything to do with memory as the memory being taken up by the particles is around 900mb.

the touch events firing in each hemisphere:

local touching = 0

script.Parent.Touched:Connect(function(hit)
	if hit.Name == "Particle" and hit ~= script.Parent.Parent.Particle and not table.find(script.Parent.Parent.Right:GetTouchingParts(), hit) then
		touching += 1
	end
	script.Parent.num.Value = touching
	wait()
end)

script.Parent.TouchEnded:Connect(function(hit)
	if hit.Name == "Particle" and hit ~= script.Parent.Parent.Particle and table.find(script.Parent:GetTouchingParts(), hit) then
		touching -= 1
	end
	script.Parent.num.Value = touching
	wait()
end)

The script updating the particle itself:

local Part = script.Parent
while wait() do
	Part.Orientation = Part.Orientation + Vector3.new(0, 180 + 17 * math.sign(script.Parent.Parent.Right.num.Value - script.Parent.Parent.Left.num.Value) * (script.Parent.Parent.Right.num.Value + script.Parent.Parent.Left.num.Value))
	--Part.BodyVelocity.Velocity = Part.CFrame.lookVector * 6 --Move forward
	Part.CFrame = Part.CFrame + Part.CFrame.lookVector * 0.67
end

If it is either the while loop or the touch events, is there any sort of fix or something I could use to reduce the amount of lag that is being caused?

I don’t think there’s much you can do about the lag. Firing so many .Touched events and running so many continious loops is as expected very performance heavy. You are doing all those long calculations in large number of scripts rapidly, so the end result ultimately depends on how capable your computer is and how much memory is available. 900mb is relative number. This must be quite a stress test.

Quick disclaimer: I can’t confirm how those videos are made, but I think I can safely say that not using real simulation. I don’t make such graphical simulations and can’t guarantee that what I said applies, even though the likelyhood is pretty high.

When it comes to graphical content, we are talking about a different story. Those videos contain large number of particles, because they are not created real-time and recorded. A normal computer hardly handles large amounts of particles and so many processes. Instead, we are talking about animations, which are slowly rendered. No demanding while-loops are running to simulate behaviour real-time, because it’s a graphical simulation, and the computer doesn’t need to simulate real physics. Videos have long rendering times, because each frame is rendered slowly, without overloading your computer. Any machine can later play that video, as long as the graphics card is capable of processing a little more demanding animations.

As far as your code goes, I think it’s reasonable to point out that wait() in while-loop is not a good option. Write something like this instead (and store paths in variables!):

Version 1 (my personal preference):

local RunService = game:GetService("RunService")

-- Find paths in advance, not repeatedly inside the loop.
local part = script.Parent
local rightValue = script.Parent.Parent.Right.num
local leftValue = script.Parent.Parent.Left.num

RunService.Heartbeat:Connect(function()
	part.Orientation = part.Orientation + Vector3.new(
		0, 180 + 17 * math.sign(rightValue.Value - leftValue.Value) *
		(rightValue.Value + leftValue.Value)
	)
	--Part.BodyVelocity.Velocity = Part.CFrame.lookVector * 6 --Move forward
	part.CFrame = part.CFrame + part.CFrame.lookVector * 0.67
	-- RunService is far more consistent.
end)

Version 2:

local RunService = game:GetService("RunService")

-- Find paths in advance, not repeatedly inside the loop.
local part = script.Parent
local rightValue = script.Parent.Parent.Right.num
local leftValue = script.Parent.Parent.Left.num

while (true) do	
	part.Orientation = part.Orientation + Vector3.new(
		0, 180 + 17 * math.sign(rightValue.Value - leftValue.Value) *
		(rightValue.Value + leftValue.Value)
	)
	--Part.BodyVelocity.Velocity = Part.CFrame.lookVector * 6 --Move forward
	part.CFrame = part.CFrame + part.CFrame.lookVector * 0.67
	-- RunService is far more consistent.
	RunService.Heartbeat:Wait()
end
2 Likes