Molang¶
Animation schema 4 accepts Molang in animation programs, vector track components, visibility track values, and dynamic NBT values. Both the short and long prefixes are supported: q or query, v or variable, and t or temp.
Programs¶
Animation-level programs are optional:
"molang": {
"initialize": "v.speed = 2;",
"tick": "v.phase = v.phase + q.delta_time * v.speed;"
}
initializeruns when a playback cycle begins.tickruns before track values are evaluated on each animation tick.v.*variables persist within the current cycle and may be assigned byinitializeandtick.t.*variables exist only for one expression evaluation.q.*values are read-only. Assigning a query is rejected.server_syncAnimations cannot usemolang.tickbecause their timeline may begin at an arbitrary synchronized time.
A new Molang session is created for every repeated cycle and every Animation segment in a Sequence.
Math functions¶
All functions in the Bedrock Molang math.* reference are supported, including the easing, random, dice, interpolation, angle, and sign functions. Trigonometric inputs and outputs use degrees.
Conditionals¶
Bedrock's binary and ternary conditional operators are supported. Only the selected branch is evaluated, and either branch may contain a brace-delimited execution scope:
q.is_moving ? {
v.speed = q.ground_speed;
} : {
v.speed = 0;
};
return v.speed;
Conditional expressions associate from the right, so a ? b : c ? d : e is equivalent to a ? b : (c ? d : e). Molang does not define separate if or else keywords; use ? and : instead.
Loops¶
loop(count, { ... }) repeats an execution scope and supports break and continue. The runtime limits one loop to 1,024 iterations:
v.count = 0;
loop(3, {
v.count = v.count + 1;
});
return v.count;
Track values¶
Each position, rotation, or scale component may be a number or a Molang string:
"rotation": [
{
"time": "0t",
"value": [0, "q.target_y_rotation", "v.offset"]
}
]
Visibility values may be booleans or Molang strings. A finite result of 0 is hidden; any other finite result is visible.
Track values may read persistent variables but cannot assign them. Temporary variables are cleared for each expression evaluation.
Dynamic NBT values¶
An NBT keyframe can use Molang to produce a compound SNBT string:
"value": {
"molang": "q.is_sneaking ? '{Glowing:1b}' : '{Glowing:0b}'"
}
The expression follows the same read-only track-expression rules as vector and visibility values. Its result must be a string containing valid compound SNBT. It is evaluated once when the keyframe is applied, rather than on every animation tick; a new playback loop or Sequence segment evaluates it again. q.key_frame_lerp_time is 0 during evaluation.
Runtime-owned fields remain forbidden. The 0t result establishes the top-level fields that later keyframes may modify, and a dynamic 0t value must return the same field set on every playback cycle.
Queries¶
The table uses the q.* form. The equivalent query.* names are also accepted.
| Query | Value |
|---|---|
q.anim_time |
Current timeline time in seconds. |
q.anim_time_ticks |
Current timeline time in ticks. |
q.anim_length |
Timeline duration in seconds. |
q.delta_time |
0.05 during normal ticks and 0 when a cycle is initialized. |
q.loop_count |
Zero-based number of completed loops. |
q.key_frame_lerp_time |
Uneased progress from the current vector keyframe to the next, from 0 to 1; 0 outside vector evaluation. |
q.life_time |
Alias of q.anim_time, for imported Molang compatibility. |
q.target_x_rotation, q.target_y_rotation |
Player look pitch and head yaw relative to the body, in degrees. |
q.body_x_rotation, q.body_y_rotation |
Player pitch and absolute body yaw, in degrees. |
q.head_x_rotation, q.head_y_rotation |
Player pitch and absolute head yaw, in degrees. |
q.eye_target_x_rotation, q.eye_target_y_rotation |
Player eye pitch and absolute head yaw, in degrees. |
q.ground_speed |
Player horizontal movement speed in blocks per second. |
q.vertical_speed |
Player vertical movement speed in blocks per second; positive is upward. |
q.modified_distance_moved |
Player walk-animation position used by imported Bedrock movement formulas. |
q.walk_distance |
Player accumulated movement distance. |
q.is_moving |
1 while the player has non-zero movement, otherwise 0. |
q.is_on_ground |
1 while the player is on the ground, otherwise 0. |
q.is_sneaking |
1 while the player is crouching, otherwise 0. |
q.is_sprinting |
1 while the player is sprinting, otherwise 0. |
q.is_swimming |
1 while the player is swimming, otherwise 0. |
q.is_gliding |
1 while the player is gliding with an elytra, otherwise 0. |
q.is_riding |
1 while the player is riding another entity, otherwise 0. |
q.is_using_item |
1 while the player is using an item, otherwise 0. |
q.is_sleeping |
1 while the player is sleeping, otherwise 0. |
q.is_emoting |
1 during player-backed emote playback, otherwise 0. |
q.item_is_charged |
1 while the player's main-hand crossbow is charged, otherwise 0. |
q.sleep_rotation |
Yaw of the bed occupied by the player, or 0 while not sleeping. |
q.is_on_fire |
1 while the player is on fire, otherwise 0. |
q.is_in_water |
1 while the player is in water, otherwise 0. |
q.health, q.max_health |
Player current and maximum health in health points (two points per heart). |
q.is_alive |
1 while the player is alive, otherwise 0. |
q.is_spectator |
1 while the player is in spectator mode, otherwise 0. |
q.head_is_in_water |
1 while the player's eyes are in water, otherwise 0. |
q.is_in_lava |
1 while the player is in lava, otherwise 0. |
q.is_in_water_or_rain |
1 while the player is in water or exposed to rain, otherwise 0. |
q.hurt_time |
Remaining player hurt-animation time in ticks. |
q.death_ticks |
Elapsed player death-animation time in ticks. |
q.invulnerable_ticks |
Remaining player invulnerability timer in ticks; this is not the permanent invulnerability flag. |
q.player_level |
Player experience level. |
q.item_in_use_duration |
Elapsed active item-use time in seconds, capped at the item's maximum use duration. |
q.item_remaining_use_duration |
Remaining active item-use time in seconds. |
q.item_max_use_duration |
Maximum active item-use duration in seconds. |
q.is_item_equipped |
Main-hand shortcut: 1 when the main hand is not empty, otherwise 0. |
q.blocking |
1 while the player is actively blocking, otherwise 0. |
q.is_eating |
1 while the player is using an item with the eat animation, otherwise 0. |
q.is_jumping |
1 while the player's latest client input has jump held, otherwise 0. |
q.is_crawling |
1 while the player has the crawling pose without swimming, otherwise 0. |
q.is_invisible |
1 while the player is invisible, otherwise 0. |
q.is_levitating |
1 while the player has the levitation effect, otherwise 0. |
q.yaw_speed |
Player yaw change during the current tick, in degrees. |
q.on_fire_time |
Remaining player fire time in seconds. |
Player-state queries refer to the player during player-backed playback. Synthetic stress-test playback has no player and evaluates these queries as 0.
The three item-use duration queries refer to the item currently being used, in either hand, and return 0 when no item is being used.
Query functions¶
Registered query functions are available in animation programs, vector and visibility tracks, and dynamic NBT values.
| Query | Value |
|---|---|
q.any(value, candidate, ...) |
1 if any candidate equals the first value. Strings and numbers retain their types. |
q.all(value, candidate, ...) |
1 if every candidate equals the first value. Strings and numbers retain their types. |
q.approx_eq(value, candidate, ...) |
1 if every numeric candidate approximately equals the first value. |
q.in_range(value, minimum, maximum) |
1 if the value is within the inclusive range. |
q.position(axis) |
Player position on axis 0 (X), 1 (Y), or 2 (Z). |
q.position_delta(axis) |
Player movement during the current tick on the selected axis. |
q.movement_direction(axis) |
Selected component of the normalized current movement vector, or 0 while stationary. |
q.is_item_equipped() |
1 if the main hand is not empty. An optional hand or equipment-slot selector may be supplied. |
q.item_is_charged() |
1 if the main-hand crossbow is charged. An optional hand or equipment-slot selector may be supplied. |
q.is_item_name_any(slot, name, ...) |
1 if the selected equipment item has one of the full identifiers, such as 'minecraft:bow'. |
q.scoreboard(objective) |
Player score for the named objective, or 0 when the objective or score is absent. |
Item selectors accept main_hand, off_hand, slot.weapon, slot.weapon.mainhand, slot.weapon.offhand, and slot.armor.head, slot.armor.chest, slot.armor.legs, or slot.armor.feet. Numeric hand selector 0 means main hand and 1 means off hand. Scalar q.is_item_equipped and q.item_is_charged remain available as main-hand shortcuts.
Validation¶
Each Molang source string is limited to 16,384 characters. Invalid syntax, unsupported query names, query assignments, and persistent-variable assignments in track values reject the Animation during loading. A numeric value that evaluates to a non-finite number stops playback as a runtime failure. A dynamic NBT value also fails at runtime if it does not return a string containing valid compound SNBT or violates the NBT track's field restrictions.
Current limitations¶
This is not a complete Bedrock Molang environment. Only the queries and query functions listed above are available. Context values, this, structs, arrays, resource values, entity references, the arrow operator's entity switching, and for_each are not supported. Null coalescing and string equality currently follow the embedded evaluator's behavior rather than full Bedrock semantics.