Does my NPC Move System like Steal A Brainrot uses too many task.spawns()?

Currently, my script uses a task.spawn for every character that is spawned every 3.5 seconds. I was wondering if this is innefficient and possible how to optimize it

while task.wait(3.5) do -- loop that runs function

	task.spawn(function()
		module.SpawnCharacter()
	end)

end


	function module.SpawnCharacter() -- function that spawns the character
		local NPC = PlaceHoldernpc:Clone()
		NPC.Parent = workspace
		NPC.HumanoidRootPart:SetNetworkOwner(nil)
		module.MoveNPCALONGPATH(NPC)
	end

This function uses a folder with parts which are named numbers based on their path order. The folder also has a part named Startblock and EndBlock. The npc is placed at start block and moves to end block when there is no more increment path position

function module.MoveNPCALONGPATH(npc, humanoid) 
	npc:PivotTo(StartBlock.CFrame)
	for i, waypoint in pairs(PathFolder:GetChildren()) do
		local PathBlock = PathFolder:FindFirstChild(i)
		if PathBlock then
			humanoid:MoveTo(PathBlock.Position)
			humanoid.MoveToFinished:Wait()
		else
			humanoid:MoveTo(EndBlock.Position)
			humanoid.MoveToFinished:Wait()
			npc:Destroy()

			break
		end

	end
end

I cut out some of the code so that it would be easier to read. so just assume that the script already works

it shouldn’t be a problem.

@MrNobodyDev is right, the code doesn’t seem intensive so it really shouldn’t be a problem, one thing I’ll mention though is that it’s typically suggested not to use task.spawn unless you specifically need the function to instantly start running, down to the current exact moment in the frame; using task.spawn means the executor immediately gets to work on your new function and can’t work on anything else until it recognises a pause (eg. task.wait) which really isn’t necessary.

Instead, you should ideally be using task.defer, which isn’t as clear as task.spawn but is definitely the go-to for your case and most others. It’ll queue up work for once the current frame is over, and then chew through each task until a pause to move onto the next, which alleviates sudden mid-frame workloads & is easier to locate in the MicroProfiler if something does stress the server/client (I recognise this code likely runs on the server but this is more-so just a guide on what you should typically be doing aswell as for this current case)