How Respawn Detection Works
A behavior pack animation controller is a small state machine attached to an entity definition. Unlike resource pack animation controllers, which play visual animations and sounds, behavior pack controllers can execute slash commands, trigger entity events, and toggle Molang variables directly on the server.
To catch a respawn, the controller needs at least two states: one representing a living player and one representing a dead player. When the player dies, the controller transitions from the alive state into the dead state. While the player sits on the death screen, the controller stays in that dead state. The moment the player clicks Respawn, their life query flips back to true, pushing the controller back into the alive state and firing any commands attached to that transition.
The standard Molang query for this check is query.is_alive. While the player is alive and moving around, query.is_alive returns 1.0. As soon as their health drops to zero and the death screen appears, query.is_alive returns 0.0.
Writing the Respawn Animation Controller
Create a JSON file inside your behavior pack's animation_controllers folder. The file defines a controller with two states: default (when the player is alive) and dead (when the player is incapacitated). Using default as the alive state prevents your respawn commands from firing the very first time a player joins the world.
Commands can be placed either in the on_exit array of the dead state or in the on_entry array of a third respawn state. Putting them in on_exit of the dead state is the most compact method because the player can only leave the dead state by respawning. Every string inside the on_exit array that begins with a forward slash is executed as a slash command from the context of that specific player.
| Entry Prefix | What it does | Notes |
|---|---|---|
| / (Forward slash) | Runs a standard slash command as the entity. | Target @s always refers to the respawning player. |
| @s (Event syntax) | Triggers an entity event defined in player.json. | Format is @s namespace:event_name. |
| v. or variable. | Executes a raw Molang assignment. | Must end with a semicolon, e.g., v.deaths = v.deaths + 1; |
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.player.respawn_commands": {
"initial_state": "alive",
"states": {
"alive": {
"transitions": [
{
"dead": "!query.is_alive"
}
]
},
"dead": {
"transitions": [
{
"alive": "query.is_alive"
}
],
"on_exit": [
"/effect @s resistance 10 4 true",
"/tellraw @s {\"rawtext\":[{\"text\":\"You have respawned with temporary spawn protection.\"}]}",
"@s custom:on_player_respawn"
]
}
}
}
}
}Attaching the Controller to the Player
An animation controller does nothing until it is registered and ticked inside an entity definition. To run respawn commands on players, you must include a modified player.json file in your behavior pack's entities folder. Inside the description block of that file, you map a short name to your controller's identifier under animations, and then tell the game to run that short name inside the scripts.animate array.
Because two behavior packs cannot both override BP/entities/player.json at the same time, keep your changes to the description header clean and organized if you are merging this feature into a larger project.
{
"format_version": "1.18.20",
"minecraft:entity": {
"description": {
"identifier": "minecraft:player",
"is_spawnable": false,
"is_summonable": false,
"is_experimental": false,
"animations": {
"respawn_tracker": "controller.animation.player.respawn_commands"
},
"scripts": {
"animate": [
"respawn_tracker"
]
}
},
"components": {
"minecraft:type_family": {
"family": [
"player"
]
}
},
"events": {
"custom:on_player_respawn": {
"add": {
"component_groups": []
}
}
}
}
}Timing Caveats and Tick Delays
Commands in the on_exit block of the dead state run on the exact server tick that query.is_alive becomes true. For most commands like /effect, /tag, /scoreboard, or /give, this timing is completely fine. However, certain spatial or camera commands can behave strangely if executed on the very first tick of respawn before the client has finished loading the spawn chunk.
If you notice a command failing or a teleport rubber-banding, combine the animation controller with a behavior pack animation (an timeline file in BP/animations/) rather than running the command directly inside the controller. Have the dead state transition into a respawning state that plays a one-second behavior animation, and place the slash command on the 0.5 or 1.0 second keyframe of that animation.
Alternative: Script API PlayerSpawnAfterEvent
If your add-on already uses the @minecraft/server Script API module, you do not need to override player.json or build an animation controller just to detect respawns. The stable world.afterEvents.playerSpawn event fires both when a player joins the world and when they respawn after dying.
The event payload includes an initialSpawn boolean property. When initialSpawn is false, the player has just respawned from death, and you can call player.runCommandAsync() or manipulate components directly in JavaScript without touching entity JSON files.
Which versions this applies to
Applies to Bedrock Edition 1.10.0 and newer for the animation controller format, and 1.16.100+ for the scripts.animate block in entity definitions. No experimental toggles are required.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Content Log Error: [Animation][error]-controller.animation.player.respawn_commands | Failed to parse animation controller | You placed the animation controller inside the Resource Pack (RP/animation_controllers/) instead of the Behavior Pack, or used resource-pack-only keys. Resource pack controllers cannot run slash commands or trigger entity events. | Move the file to BP/animation_controllers/ and ensure the format_version at the top of the controller file is set to "1.10.0". |
| Respawn commands run every time the player logs into the world or changes dimensions. | Your initial_state is set to "dead", or you placed your commands in the on_entry array of the "alive" state. Whenever a player loads into a world, the controller initializes into its starting state and runs that state's on_entry list. | Set initial_state to "alive" and place your respawn commands inside the on_exit array of the "dead" state so they only run after an actual death. |
| The player dies and respawns, but nothing happens and no errors appear in the Content Log. | The short name defined under description.animations in BP/entities/player.json is missing from the description.scripts.animate array, or another behavior pack higher in the world's load order is overriding player.json. | Verify that the short name is listed inside scripts.animate in BP/entities/player.json, and check that no other active pack in the world contains its own player.json. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
