Fast and efficient map loader / unloader

Hey! I am working on a game which will have a map rotation system, much like Phantom Forces and Arsenal.

The difference is my game will have large maps with high part counts, so I am wondering how I could improve my code to make the loading faster with as less lag as possible!

local MaxIterationsUntilWait = 100
local i = 0

for _, v in pairs(StructureFolder:GetChildren()) do
    if i >= MaxIterationsUntilWait then
        i = 0 
        RunService.Heartbeat:Wait()
    else
        i += 1
    end

    local clone = v:Clone()
    clone.Parent = WorkspaceMapFolder
end

Basically after every 100 iterations the script will wait a heartbeat adding some kind of delay instead of just going trough it all instantly and lagging a lot.

The script already works fine but it can take a couple dozen seconds which I’m trying to improve

If you have any recommendations, let me know!

If you intend to load the map in by “chunks”, then the best thing is to make the chunks big enough to where you don’t have too many chunks, but small enough to where it will still not lag the server out.

Out of curiousity, what are you loading in that takes dozens of seconds? It doesn’t seem like this script should take that long to do it.

Your current approach is a good one for reducing lag, as it allows the game to process other events and updates while the loop is running. However, there are a few changes you could make to further improve the speed and performance of the loop.

One optimization you could make is to use the ipairs function instead of pairs when iterating over the children of StructureFolder . This is because ipairs is faster and more efficient when iterating over arrays (which is what StructureFolder:GetChildren() returns), while pairs is better suited for tables.

Another optimization you could make is to use a local variable to store the result of StructureFolder:GetChildren() , rather than calling the method each time through the loop. This will save time and improve performance by avoiding the overhead of calling the method repeatedly.

Here is an example of how you could implement these changes:

local MaxIterationsUntilWait = 100
local i = 0

-- Store the children of StructureFolder in a local variable
local structureChildren = StructureFolder:GetChildren()

-- Use ipairs to iterate over the children
for _, v in ipairs(structureChildren) do
    if i >= MaxIterationsUntilWait then
        i = 0 
        RunService.Heartbeat:Wait()
    else
        i += 1
    end

    local clone = v:Clone()
    clone.Parent = WorkspaceMapFolder
end
1 Like

There are a few things you can try to improve the performance of your map loading script:

  1. Use Instance.new("Folder") instead of WorkspaceMapFolder to temporarily store the cloned parts, and then move them all to WorkspaceMapFolder once they are all cloned. This will reduce the number of Parent changes that need to be made, which can be quite expensive.
  2. Consider using Instance.new("Model") instead of Instance.new("Folder") to temporarily store the cloned parts. This will allow you to use the Model:MoveTo() function to move the parts all at once, rather than individually changing the Parent of each part.
  3. Use pcall() to wrap the cloning and parenting operations in a try-catch block, in case any of the parts fail to clone or parent. This will allow the script to continue executing even if there are errors, rather than stopping execution and causing the map loading to fail.
  4. Use wait() instead of RunService.Heartbeat:Wait() to add a delay between iterations. wait() is generally more efficient than RunService.Heartbeat:Wait() because it only waits for the next frame to be rendered, rather than waiting for the next update of the RunService.
1 Like