How would I make this script use less rate/activity?

I made a script for moving multiple models using setprimarypartcframe but it messes up when a big amount (70-100) of models move. At first I was using individual loops for each model, then I changed it to one loop for all models but it still didn’t capture the effect I wanted. How would I optimize this?

    for i,v in pairs (Map:WaitForChild("Enemies"):GetChildren()) do
        EnemySteppers[v] = {
            Configure = v.Configure,
            prevNode = Map.Spawners.EnemySpawner.CFrame.Position,
            CurrNode = v.Configure.CurrNode.Value,
            Speed = v.Configure.Speed,
            step = 0,
        }
    end    

    coroutine.resume(coroutine.create(function()
        while true do
            for i,v in pairs (EnemySteppers) do
                if v and v.Configure then
                    local Enemy = v
                    local EnemyConfigure = v.Configure
                    local prevNode = v.prevNode
                    local CurrNode = v.CurrNode
                    local Speed = v.Speed.Value
                    if CurrNode ~= 0 and v.prevNode ~= Vector3.new(0,0,0) then
                        if thisPath.Path[CurrNode] ~= nil and i:WaitForChild("HumanoidRootPart")  then

                            local steps = 50/Speed * ((prevNode - thisPath.Path[CurrNode].Position).magnitude / 1)
                            local step = math.min(v.step + (1/steps),1)
                            if step >= 1 and thisPath.Path[CurrNode+1] then
                                i:SetPrimaryPartCFrame(CFrame.new(prevNode:lerp(thisPath.Path[CurrNode].Position, step), thisPath.Path[CurrNode+1].Position)* CFrame.new(0,.6,0))
                            else
                                i:SetPrimaryPartCFrame(CFrame.new(prevNode:lerp(thisPath.Path[CurrNode].Position, step), thisPath.Path[CurrNode].Position)* CFrame.new(0,.6,0))
                            end
                            v.step=step
                            if v.step >= 1 then 
                                if thisPath.Path[CurrNode+1] ~= nil then
                                    v.prevNode = thisPath.Path[CurrNode].Position
                                    v.CurrNode = v.CurrNode + 1
                                    v.step = 0
                                else
                                    EnemySteppers[i] = nil
                                    wait(0)
                                    i:Destroy()
                                end
                            end
                        end
                    end
                end
            end
            game:GetService("RunService").Stepped:Wait()
        end
    end))

I tested this, performance is greatly increased when moving the PrimaryPart with every other part welded to it rather than using SetPrimaryPartCFrame.
To do this, unanchor every part besides the PrimaryPart and weld the parts to the PrimaryPart. This should make it run much better. I had no performance issues when moving 100 models like this.

here are some demo projects that might help you
SpawnEnemys.rbxl (36.7 KB)
Server_keeping_track_of_enemy_positions.rbxl (33.9 KB)
spawn_enemys_without_a_loop.rbxl (35.0 KB)
500_enemys_running_at_60_fps.rbxl (36.2 KB)
FollowPath.rbxl (42.9 KB)

1 Like