---
id: annot-ondespawn
name: @OnDespawn
category: annotations
kind: annotation
tokens: @OnDespawn
sig: @OnDespawn(Model, reason: r) handler Name { … }
tip: Run a handler when a model instance is torn down, optionally knowing why.
order: 50
---
@OnDespawn(Model) is the teardown counterpart to @OnSpawn: it fires once for each instance of the named model as it is removed, whether by an in-world despawn or at program shutdown, and its body still reads the instance's outgoing field values before they are gone. With the optional reason: r binding it becomes reason-carrying teardown — r is bound to an EndReason the compiler passes at each teardown site (an in-world despawn passes EndReason.Despawned, program exit passes EndReason.Quit) so one hook can branch on why the instance is ending, the way Unreal's EndPlay(reason) does. Every still-live instance's hook fires at quit, which makes "no silent deaths" real: drop loot on a real death but skip it when the app is simply closing. Add @Public to also emit a model_<Model>_despawn event.
```ludic
program DespawnHook {
property Health { current: int = 0 }
property Loot { gold: int = 0 }
model Enemy { Health, Loot }
@OnDespawn(Enemy, reason: teardown_reason) handler DropLoot {
match teardown_reason {
EndReason.Quit => {} # app closing — do not drop loot
_ => { print(Loot.gold) } # died in-world — award the gold
}
}
handler SpawnWave phase Start { spawn Enemy { Health { current: 10 }, Loot { gold: 25 } } }
handler KillOne phase Render {
for (Health) in query [Health, {Enemy}] { despawn self() } # prints 25
quit()
}
}
```