The Core Riding Setup
Before an entity can fly with a rider, it must accept a passenger and hand over directional control. This requires two primary components in your behavior file: minecraft:rideable and minecraft:input_ground_control.
Even though the entity will leave the ground, minecraft:input_ground_control is mandatory. It binds the player's WASD or thumbstick inputs to the entity's movement vector and forces the entity to face the direction the player is looking. You should place minecraft:input_ground_control inside a component group and add it via the on_rider_mounted trigger on minecraft:rideable, then remove it on on_rider_dismounted so the entity's AI can take back over when unmanned.
For an entity to move while airborne without plummeting, you must also disable standard gravity by setting has_gravity to false in minecraft:physics. Without gravity, standard ground movement speeds do not apply the same way, so you will need to pair minecraft:movement with minecraft:underwater_movement or rely on vertical velocity adjustments.
| Component | What it does | Notes |
|---|---|---|
| minecraft:rideable | Defines seat positions, family types allowed to mount, and mount/dismount events. | Required on all mounts. |
| minecraft:input_ground_control | Allows the seated player to steer the entity using standard movement keys. | Only add while a player is actually mounted. |
| minecraft:physics | Controls collision and gravity. | Set has_gravity to false for true hovering mounts. |
| minecraft:can_fly | Marks the entity as capable of flight for pathfinding and movement calculations. | Takes no parameters; prevents fall damage and unlocks air speeds. |
Method 1: Pitch-Controlled Gliding and Flight
The cleanest JSON-only way to let a player fly up and down is to link vertical velocity to the player's camera pitch. When a player rides an entity with minecraft:input_ground_control, the entity's head pitch matches the rider's camera pitch. You can read this angle using the Molang query query.target_x_rotation.
By running an animation or animation controller on the server side (linked in the behavior pack's description block), you can apply the levitation effect or trigger events based on whether the player is looking up or down. However, a smoother pure-JSON trick combines minecraft:underwater_movement with a zero-gravity physics component. When has_gravity is false and minecraft:can_fly is present, the game treats air movement similarly to fluid movement, allowing the mount to drift along its facing vector.
Because pure zero-gravity drift can feel slippery and sometimes fails to climb steeply without assistance, many creators attach a repeating behavior pack animation that nudges the entity upward when the rider looks above the horizon, and applies slow_falling or downward levitation when looking down.
Method 2: Jump-to-Ascend with Horse Jump
If you want the player to press the Jump key (Spacebar or A button) to gain altitude and glide down naturally when releasing it, you can repurpose minecraft:horse.jump_strength.
Normally, minecraft:horse.jump_strength charges a jump bar and launches a mount off the ground. When paired with minecraft:can_fly, jumping works even in mid-air. The player can tap or hold the jump key to thrust upward repeatedly. To keep the entity from falling like a stone between jumps, apply a permanent slow_falling mob effect via an animation or give the entity a very light downward glide using vertical movement components.
Note that adding minecraft:horse.jump_strength replaces the player's experience bar with the mount jump gauge while riding, and hides the hunger bar in favor of mount health.
{
"format_version": "1.20.80",
"minecraft:entity": {
"description": {
"identifier": "wiki:griffin",
"is_spawnable": true,
"is_summonable": true
},
"component_groups": {
"wiki:ridden": {
"minecraft:input_ground_control": {},
"minecraft:can_fly": {},
"minecraft:horse.jump_strength": {
"value": {
"range_min": 0.6,
"range_max": 1.2
}
}
},
"wiki:unridden": {
"minecraft:behavior.random_stroll": {
"priority": 5,
"speed_multiplier": 1.0
}
}
},
"components": {
"minecraft:type_family": {
"family": ["griffin", "mob"]
},
"minecraft:health": {
"value": 40,
"max": 40
},
"minecraft:movement": {
"value": 0.35
},
"minecraft:underwater_movement": {
"value": 0.35
},
"minecraft:movement.basic": {},
"minecraft:navigation.walk": {
"can_path_over_water": true
},
"minecraft:physics": {
"has_gravity": true,
"has_collision": true
},
"minecraft:tameable": {
"probability": 1.0,
"tame_items": ["minecraft:golden_apple"]
},
"minecraft:rideable": {
"seat_count": 1,
"crouching_skip_interact": true,
"family_types": ["player"],
"interact_text": "action.interact.ride.horse",
"seats": [
{
"position": [0.0, 1.1, -0.2]
}
],
"on_rider_mounted": {
"event": "wiki:on_mounted",
"target": "self"
},
"on_rider_dismounted": {
"event": "wiki:on_dismounted",
"target": "self"
}
}
},
"events": {
"minecraft:entity_spawned": {
"add": {
"component_groups": ["wiki:unridden"]
}
},
"wiki:on_mounted": {
"remove": {
"component_groups": ["wiki:unridden"]
},
"add": {
"component_groups": ["wiki:ridden"]
}
},
"wiki:on_dismounted": {
"remove": {
"component_groups": ["wiki:ridden"]
},
"add": {
"component_groups": ["wiki:unridden"]
}
}
}
}
}Method 3: Script API Velocity Control
In modern Bedrock development, the most responsive way to handle flying mounts is through the @minecraft/server Script API. Instead of fighting vanilla gravity and potion effects, you read the rider's view direction every tick and apply an impulse or velocity directly to the mount.
In your behavior JSON, you still need minecraft:rideable so the player can sit on the entity, and minecraft:input_ground_control so the entity rotates smoothly with the player's camera. However, the script handles the actual propulsion. Using entity.getComponent('minecraft:rideable'), you can fetch the current riders, get the player's view direction via player.getViewDirection(), and apply that vector to the mount using entity.applyImpulse() or entity.clearVelocity() depending on how tight you want the turning radius to feel.
This approach also allows you to detect whether the player is jumping or sneaking via player.inputInfo or button state queries in recent script versions, giving you true helicopter-style vertical controls without hijacking the horse jump bar.
import { world, system } from "@minecraft/server";
system.runInterval(() => {
for (const dimensionName of ["overworld", "nether", "the_end"]) {
const dimension = world.getDimension(dimensionName);
const mounts = dimension.getEntities({ type: "wiki:griffin" });
for (const mount of mounts) {
const rideable = mount.getComponent("minecraft:rideable");
if (!rideable) continue;
const riders = rideable.getRiders();
if (riders.length === 0) continue;
const driver = riders[0];
if (driver.typeId !== "minecraft:player") continue;
const viewDir = driver.getViewDirection();
const speed = 0.8;
mount.clearVelocity();
mount.applyImpulse({
x: viewDir.x * speed,
y: viewDir.y * speed,
z: viewDir.z * speed
});
}
}
}, 1);Preventing Fall Damage and AI Conflicts
When a player dismounts a flying entity high in the air, or lands hard after a steep dive, both the mount and the rider are at risk of taking lethal fall damage. Always include the minecraft:damage_sensor component on your flying entity with a deal_damage: false filter for the fall cause.
Additionally, never leave AI movement behaviors (such as minecraft:behavior.float, minecraft:behavior.random_fly, or minecraft:behavior.NearestAttackableTarget) active in the same state as minecraft:input_ground_control. Active AI goals will fight the player's steering inputs, causing the mount to stutter in mid-air or snap its head back toward a pathfinding node. Keep all AI goals in your unridden component group and strip them out cleanly when the mount event fires.
{
"minecraft:damage_sensor": {
"triggers": [
{
"cause": "fall",
"deals_damage": false
}
]
}
}Which versions this applies to
Applies to Bedrock Edition 1.20.80 and newer. The JSON components (on_rider_mounted, input_ground_control, horse.jump_strength) are stable and require no experimental toggles. The Script API method uses stable @minecraft/server methods available since 1.19.0+.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The player mounts the entity, can rotate it by looking around, but pressing W/A/S/D does not move it forward. | The entity is missing the minecraft:tameable component (or has not been tamed yet), or it lacks a base minecraft:movement component. | Ensure the entity has both minecraft:movement and minecraft:movement.basic, and either tame the entity in-game before riding or test whether your setup requires the tamed state for input_ground_control to engage. |
| Content Log Error: [Json][error] Failed to parse event 'on_rider_mounted' in 'minecraft:rideable'. | Your entity file's format_version is set too low. The on_rider_mounted and on_rider_dismounted callbacks inside minecraft:rideable were introduced in newer format versions (around 1.20.60+). | Raise the format_version at the top of your behavior pack entity JSON to at least 1.20.80, or use an environment sensor / tick animation with query.has_rider if maintaining an older format version. |
| The flying mount moves at a crawl in the air compared to its speed on the ground. | When an entity leaves the ground, standard ground friction and movement values drop dramatically unless air/fluid movement speeds are defined. | Add both minecraft:can_fly and minecraft:underwater_movement with a value matching your standard minecraft:movement speed. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
