Skip to main content

Pulse.Cleaner

Pulse.Cleaner runs a timed loop that collects objects from a folder or set and destroys them. Use it for performance features that remove dead titans, decorations, grass, or other world clutter.


Creating a cleaner

local cleaner = Pulse.Cleaner.new({
interval = 1.0, -- seconds between cleanup passes
collect = function()
-- return an array of instances to destroy
local folder = workspace:FindFirstChild("Titans")
and workspace.Titans:FindFirstChild("Dead")
if not folder then return {} end
local ok, list = pcall(function() return folder:GetChildren() end)
return ok and list or {}
end,
})

API

cleaner:start() -- begin the cleanup loop
cleaner:stop() -- stop the loop (does not run cleanup immediately)

Each pass calls collect(), then calls :Destroy() on every instance in the returned array. Errors in collect are silently swallowed — the loop continues on the next interval.


TypeScript example

// src/misc/Performance.ts
defineComponent('Performance', () => {
const enabled = signal(false)
const selected = signal<Record<string, boolean>>({})

const paths: Record<string, () => Folder | undefined> = {
'Dead Titans': () => Pulse.World.find('Titans', 'Dead') as Folder | undefined,
'Decor': () => Pulse.World.find('Map', 'Decor') as Folder | undefined,
'Trees': () => Pulse.World.find('Map', 'Trees') as Folder | undefined,
'Rocks': () => Pulse.World.find('Map', 'Rocks') as Folder | undefined,
}

const cleaners: Record<string, ReturnType<typeof Pulse.Cleaner.new>> = {}

for (const [name, pathFn] of Object.entries(paths)) {
cleaners[name] = Pulse.Cleaner.new({
interval: 1.0,
collect: () => {
const folder = pathFn()
if (!folder) return []
const [ok, children] = pcall(() => folder.GetChildren())
return ok ? children as Instance[] : []
},
})
}

function sync() {
if (!enabled()) {
for (const c of Object.values(cleaners)) c.stop()
return
}
const sel = selected()
for (const [name, c] of Object.entries(cleaners)) {
if (sel[name]) c.start() else c.stop()
}
}

on.signal(enabled, sync)
on.signal(selected, sync)

return [
toggle('Performance Mode').bind(enabled),
multidropdown('Clean Up', {
options: Object.keys(paths),
}).bind(selected),
]
})

When to use it

Pulse.Cleaner is for bulk periodic cleanup — many objects piling up in a folder that you want to remove on a schedule. If you need to remove a specific set of objects once (not repeatedly), use a plain for loop.

For workspace navigation, pair it with Pulse.World.find to safely resolve the folder path each pass — the folder may not exist at startup but could appear later.


Limitations

  • :Destroy() is called on every object in the collected array every pass. Do not use it for objects you need later.
  • There is no :flush() method — stopping the cleaner does not immediately destroy pending objects.
  • If collect returns a large array frequently, it can spike frame time. Keep interval reasonable (≥ 0.5 s for high-count folders).