entity_signals
Per-entity destroy signals, surfaced on the entity proxy as `entity(id).onDestroying` and `entity(id).onDestroyed`, plus the dispatch the despawn pipeline calls to fire them.
entity_signals
Per-entity destroy signals, surfaced on the entity proxy as
entity(id).onDestroying and entity(id).onDestroyed, plus the dispatch
the despawn pipeline calls to fire them.
local boss = entity.find("Boss")
boss.onDestroying:Connect(function()
-- runs BEFORE teardown — final state is still readable
saveBossStats(boss.component.get("Combatant").public)
end)
boss.onDestroyed:Connect(function()
log.info("boss fully cleaned up")
end)
entity.despawn(boss.id) -- onDestroying fires, then teardown, then onDestroyed
Order
onDestroying and onDestroyed are Signals (see signal.module),
created on first access. The despawn pipeline drives the order. For a
cascade rooted at one entity.despawn(root) call:
onDestroyingfires across the whole subtree, root first — before any component teardown, so handlers read final state.- components tear down (
onDestroy(self)per component), leaves first. onDestroyedfires per entity as it is removed, leaves first.
onDestroying handlers must not yield, and the entity is frozen against
reparenting / re-mutation during the destroying window.
An entity nobody observes costs nothing and fires nothing.
Scoped to this part · feeds back into the world's score.