Unity's coroutines do exactly that.

The problem
A timer in Update, for one delay.
float _respawnAt;bool _waiting; void Update(){ if ( _waiting && Time.time >= _respawnAt ) { _waiting = false; Respawn(); }}
Two fields and a check every frame, all to wait once. Add three more delays and Update is a mess.
The fix
Pause a method, not the game.
A coroutine is a method that can stop halfway, let the game keep running, and pick up later.
run→yield→resume
The fix in code
yield return WaitForSeconds.
void Die(){ StartCoroutine( RespawnAfter( 3f ) );} IEnumerator RespawnAfter( float seconds ){ yield return new WaitForSeconds( seconds ); Respawn();}
The wait reads top to bottom, like the sentence it is. No fields, nothing in Update.
Watch out
Two ways it stops early.
Coroutines belong to their GameObject, and they follow the game's clock.
- GameObject disabled
- coroutine stops
- Time.timeScale = 0
- wait never ends
- Wait while paused
- WaitForSecondsRealtime
The rule
Wait with a coroutine, not a timer.
- Start it
- StartCoroutine( Fn() )
- Wait
- yield return WaitForSeconds
- While paused
- WaitForSecondsRealtime