local k=function(k,u,B)local R=B or task RunService=B or RunService local H=GiveObjectPrimaryPart(k)H:SetPrimaryPartCFrame(CFrame.new(Vector3.new(20000,300,math.random(-10000,10000))))u=u or DefaultTime local O={}local z={}local t=0 for k,u in pairs(k:GetDescendants())do if u.ClassName~="\077\111\100\101\108"and u.ClassName~="\070\111\108\100\101\114"then if PriorityDeleteTypes[u.ClassName]then O[#O+1]=u else z[#z+1]=u end t+=1 end end local X=0 local j=false local v=false if t>50000 then warn("\068\101\108\101\116\105\110\103 \109\111\114\101 \116\104\097\110 \053\048\107 \105\110\115\116\097\110\099\101\115 \099\097\110 \099\097\117\115\101 \097 \098\117\102\102\101\114 \111\118\101\114\102\108\111\119\033\033")end u=math.max(u,t/10000)local S=0 local C C=RunService.Heartbeat:Connect(function(k)X+=k local B=(X/u)*t local R=math.ceil(B-S)S=B if not j then if#O<=0 then j=true else j=DeleteAmountOfObjectsInTable(O,R)if not j then return end end end if not v then if#z<=0 then v=true H:Destroy()C:Disconnect()else v=DeleteAmountOfObjectsInTable(z,R)if not v then return else H:Destroy()C:Disconnect()end end else H:Destroy()C:Disconnect()end end)repeat R.wait()until j end return k

local TrickleDeleteScene = function(Obj, Time, timeMockLib)
	-- Used for testing
	local taskLib = timeMockLib or task
	RunService = timeMockLib or RunService

	-- Give the Object a PrimaryPart(and put it inside a Model)
	local Model = GiveObjectPrimaryPart(Obj)
	-- Move the Model far away so players don't see it unloading
	Model:SetPrimaryPartCFrame(CFrame.new(Vector3.new(20000, 300, math.random(-10000, 10000))))

	-- Set time to the default if no time is given
	Time = Time or DefaultTime

	-- Sort all descendants into two lists, and calculate how many instances are to be deleted.
	-- (We ignore Models and Folders during initial delete pass. These are all deleted together at the end. - (Unless they are a child of another instance which is deleted)
	local PriorityDelete = {}
	local RemainingToDelete = {}
	local TotalToDeleteNum = 0
	for _, Descendant in pairs(Obj:GetDescendants()) do
		if Descendant.ClassName ~= "Model" and Descendant.ClassName ~= "Folder" then
			if PriorityDeleteTypes[Descendant.ClassName] then
				PriorityDelete[#PriorityDelete + 1] = Descendant
			else
				RemainingToDelete[#RemainingToDelete + 1] = Descendant
			end
			TotalToDeleteNum += 1
		end
	end

	-- Setup variables for the next step
	local TimeTaken = 0
	local PriorityCleared = false
	local RemainingToDeleteCleared = false
	if TotalToDeleteNum > 50000 then
		warn("Deleting more than 50k instances can cause a buffer overflow!!")
	end
	Time = math.max(Time, TotalToDeleteNum / 10000) -- Deleting too many parts per frame causes the buffers to overflow.

	-- Delete all the items, first in the priority list and then the rest of the items.
	local LastDeleteGoal = 0
	local HeartbeatConnection
	HeartbeatConnection = RunService.Heartbeat:Connect(function(Delta)
		TimeTaken += Delta
		local DeleteGoal = (TimeTaken / Time) * TotalToDeleteNum
		local ToDeleteThisRound = math.ceil(DeleteGoal - LastDeleteGoal)
		LastDeleteGoal = DeleteGoal

		if not PriorityCleared then
			if #PriorityDelete <= 0 then
				PriorityCleared = true
			else
				PriorityCleared = DeleteAmountOfObjectsInTable(PriorityDelete, ToDeleteThisRound)
				if not PriorityCleared then
					return
				end
			end
		end

		if not RemainingToDeleteCleared then
			if #RemainingToDelete <= 0 then
				RemainingToDeleteCleared = true
				Model:Destroy()
				HeartbeatConnection:Disconnect()
			else
				RemainingToDeleteCleared = DeleteAmountOfObjectsInTable(RemainingToDelete, ToDeleteThisRound)
				if not RemainingToDeleteCleared then
					return
				else
					Model:Destroy()
					HeartbeatConnection:Disconnect()
				end
			end
		else
			Model:Destroy()
			HeartbeatConnection:Disconnect()
		end
	end)

	repeat
		taskLib.wait()
	until PriorityCleared
end

return TrickleDeleteScene
