How to avoid FPS drop when adding lots of parts at one time

Put the code below in a LocalScript. Run the project and run in-game somewhere away from center and press R on keyboard. Depending on your rig you will get ~1 sec freeze (fps drop to 1 orsmth). Is there any way to avoid it? I tough spawn (new thread) would be the rescue, but isn’t :confused:

local function addLotOfJunk()
	local parts = 50000
	local base = math.floor(parts ^(1/3))
	local holder = Instance.new("Model")
	
	local n = 0
	for x = 1, base do
		for z = 1, base do
			for y = 1, math.ceil(parts/base^2) do
				if n == parts then
					break
				end
				
				local p = Instance.new("Part")
				p.Anchored = true
				p.Locked = true
				p.CanCollide = true
				p.Material = Enum.Material.SmoothPlastic
				p.Size = Vector3.new(1,1,1)
				
				local xx = x * 1
				local yy = y * 1
				local zz = z * 1
				
				p.Position = Vector3.new(xx, yy, zz)
				
				p.TopSurface = Enum.SurfaceType.Smooth
				p.BottomSurface = Enum.SurfaceType.Smooth
				p.Color = Color3.fromRGB(125, 125, 125)
				
				local wedgeMesh = Instance.new("SpecialMesh", p)
				wedgeMesh.MeshType = Enum.MeshType.Wedge
				wedgeMesh.Scale = Vector3.new(0,1,1)
				
				p.Parent = holder
				n = n + 1
				
	
			end
		end
	end
	
	holder.Parent = workspace
end


local rPressed = false
local junkInitiated = false

game:GetService("UserInputService").InputBegan:connect(function(inputObject, gameProcessedEvent)
    if inputObject.KeyCode == Enum.KeyCode.R and rPressed == false then
		print("Adding junk in next step")
        rPressed = true
    end 
end)
 
local RunService = game:GetService("RunService")
local function onStep(currentTime, deltaTime)
  	if rPressed == true and junkInitiated == false then
		junkInitiated = true
		print("Adding junk")
		spawn(addLotOfJunk)
	end
end
RunService.Stepped:Connect(onStep)

You’re spawning in 50,544 parts without any delay. I suggest you add some delay between spawning the parts somewhere within one of your for loops, it’ll take longer to spawn them, but it’ll reduce the FPS drop. This is a trade-off you simply have to face, you can’t expect it to just spawn this many parts in as fast as possible and have smooth gameplay. What you’re experiencing is the rendering being delayed to give the priority to your parts spawning.

I don’t understand your need for spawning this many parts in such a small area, for low end devices they will definitely have a hard time rendering them all, giving them a constant low FPS count.

EDIT: The main reason for this this FPS drop is actually rendering the parts in workspace, there is actually less of a stutter if you don’t ever move the parts to workspace (obviously you want to though). You’d also need to have the parts spawn procedurally in workspace, instead of in the background and then moving them all to workspace. Parent the model of the parts to workspace sooner, and also generate the parts with some delay - this will reduce the impact and add a bit of a wait for them to spawn, but it’ll never be perfect.

2 Likes

Well, I was hoping for some Magic :slight_smile: … async processes orsmth

Most of the Roblox game engine runs on a single thread. This includes the Lua scripts and the rendering engine. There is no official API for creating a background Lua thread separate from the game engine’s main thread. Also, coroutines just create virtual threads that run and yield in series with the main thread. They don’t actually run in another CPU thread.

I recommend you do a wait() call every 100 parts or so, so that it does not completely freeze the game for however long it does. I’ll leave it up to you to find the best part interval.

1 Like