Choosing the Right Look Detection Method
Before writing any code or commands, decide whether you need to detect a general compass direction, an entity at a fixed distance, or exact line-of-sight with block collision. Pure command recipes are fast to set up in functions and command blocks without enabling scripting or editing entity behaviors, making them ideal for quick mapmaking mechanics or simple custom abilities. However, commands cannot natively trace a ray through empty air until they hit a wall without running long chains of recursive functions.
If you are building a custom mob or modifying vanilla entity behaviors in a behavior pack, the native JSON components and entity filters handle line-of-sight math in the C++ game engine. They automatically verify whether solid blocks sit between the observer and the target, which prevents your custom monsters from reacting to players through stone walls. The trade-off is that JSON components only check between two entities and cannot tell you which block coordinate a player is staring at.
For precision mechanics like custom firearms, block-inspection tools, or UI prompts that appear when hovering over interactive furniture, the `@minecraft/server` Script API provides engine-level raycasting. Scripted raycasts return the exact hit location, the block face, or the entity intersecting the player's view vector, and you can configure whether liquids or passable blocks like tall grass interrupt the beam.
| Method | Checks Obstacles? | Best Used For |
|---|---|---|
| Selector args (rx, ry) | No | Checking if a player looks up at the sky, down at the ground, or toward a compass wall. |
| Local coordinates (^ ^ ^) | Manual only | Command-only packs checking if a player aims at an entity within a known, fixed distance. |
| minecraft:lookat component | Yes (Engine LoS) | Custom mobs that freeze, aggro, or transform when a player looks directly at them. |
| Script API Raycasting | Yes (Configurable) | Long-range hitscan weapons, block inspection tools, and precise crosshair hover detection. |
Fixed-Distance Detection with Local Coordinates
In Bedrock commands, caret notation (`^left ^up ^forward`) shifts the execution position along the executor's view vector rather than the world grid. Crucially, the execution anchor defaults to the entity's feet even when using carets. To project a line from the player's actual camera, you must include the `anchored eyes` subcommand in your `/execute` chain before stepping forward with `^ ^ ^`.
Once anchored to the eyes, stepping forward by a specific number of blocks and selecting entities within a small radius (`r`) creates a detection sphere along the player's sightline. Because a single sphere only checks one specific distance, command creators chain multiple checks at increasing intervals (for example, at 2, 3.5, and 5 blocks out) to approximate a continuous cylinder of detection in front of the player.
Keep in mind that entity selection spheres check against the target entity's feet position (its origin), not its full hitbox volume. If a player looks at the head of a two-block-tall mob, a tiny radius like `r=0.5` placed at eye level might miss the mob's origin at the floor. Shifting the check slightly downward after stepping forward or using a radius between `1.0` and `1.5` compensates for the gap between a mob's feet and its torso.
# Reset the tag on all villagers before running the check
tag @e[type=minecraft:villager,tag=is_looked_at] remove is_looked_at
# Step 2, 3.5, and 5 blocks forward from the player's eyes.
# Shift down slightly on the Y axis so the radius catches the villager's feet origin.
execute as @a at @s anchored eyes positioned ^ ^ ^2 positioned ~ ~-0.8 ~ run tag @e[type=minecraft:villager,r=1.2,c=1] add is_looked_at
execute as @a at @s anchored eyes positioned ^ ^ ^3.5 positioned ~ ~-0.8 ~ run tag @e[type=minecraft:villager,r=1.2,c=1] add is_looked_at
execute as @a at @s anchored eyes positioned ^ ^ ^5 positioned ~ ~-0.8 ~ run tag @e[type=minecraft:villager,r=1.2,c=1] add is_looked_at
# Trigger an effect on any villager that was caught in the sightline
execute at @e[type=minecraft:villager,tag=is_looked_at] run particle minecraft:villager_happy ~ ~2.2 ~Angle-Based Detection with Selector Arguments
When you do not care about a specific target entity and only need to know if a player is looking at the ceiling, the floor, or a specific wall in a puzzle room, use rotation selector arguments: `rx`, `rxm`, `ry`, and `rym`. These arguments filter entities by their head pitch and yaw without casting rays or checking coordinates.
The X-rotation (`rx` for maximum, `rxm` for minimum) measures vertical pitch. Looking straight ahead at the horizon is `0.0`. Looking straight down at your feet is `90.0`, and looking straight up at the sky is `-90.0`. Because negative numbers are smaller than positive numbers, looking upward means your maximum pitch (`rx`) is a high negative number like `-75`, while your minimum (`rxm`) is `-90`.
The Y-rotation (`ry` for maximum, `rym` for minimum) measures horizontal compass heading from `-180.0` to `180.0`. South is `0.0`, West is `90.0`, North is `-180.0` (or `180.0`), and East is `-90.0`. This selector check is virtually free in terms of server performance and works anywhere in the world regardless of what blocks surround the player.
| Selector Argument | Range | Key Reference Angles |
|---|---|---|
| rxm (Min Pitch) | -90.0 to 90.0 | -90.0 is straight up; 0.0 is horizon. |
| rx (Max Pitch) | -90.0 to 90.0 | 90.0 is straight down; 0.0 is horizon. |
| rym / ry (Yaw) | -180.0 to 180.0 | 0.0 South, 90.0 West, -90.0 East, 180.0/-180.0 North. |
# Detect players looking nearly straight up at the sky (pitch between -90 and -75)
execute as @a[rxm=-90,rx=-75] at @s run title @s actionbar You are staring at the stars.
# Detect players looking straight down at the floor (pitch between 75 and 90)
execute as @a[rxm=75,rx=90] at @s run title @s actionbar You are staring at the ground.
# Detect players facing East (yaw between -105 and -75) and looking level
execute as @a[rym=-105,ry=-75,rxm=-15,rx=15] at @s run particle minecraft:endrod ^ ^ ^3Entity Component: minecraft:lookat
When creating a custom mob in a behavior pack, command-based raycasting is unnecessary because Bedrock provides the `minecraft:lookat` entity component. This is the exact component vanilla Endermen use to detect when a player stares at them. Placed inside an entity's behavior JSON, it runs native line-of-sight checks from the target's eyes to the custom mob, automatically respecting solid blocks and entity hitboxes.
The component allows you to specify a `search_radius`, whether the mob's head must rotate toward the observer via `set_target`, and a `filters` block to restrict who can trigger the reaction (for instance, ignoring players in Creative mode or players wearing carved pumpkins). When a valid observer looks at the entity, it fires the event defined in `looked_at_event` and starts a cooldown timer defined by `look_cooldown`.
To build a statue mob that freezes when watched and chases when unseen, pair `minecraft:lookat` with component groups. When `looked_at_event` fires, add a component group that sets `minecraft:movement` to `0.0` and starts a short `minecraft:timer`. If the player is still looking, `minecraft:lookat` continually refreshes the state; once the player looks away and the timer expires, fire a second event to restore normal movement.
{
"format_version": "1.20.80",
"minecraft:entity": {
"description": {
"identifier": "wiki:weeping_statue",
"is_spawnable": true,
"is_summonable": true
},
"component_groups": {
"wiki:moving_state": {
"minecraft:movement": {
"value": 0.32
}
},
"wiki:frozen_state": {
"minecraft:movement": {
"value": 0.0
},
"minecraft:timer": {
"looping": false,
"time": 0.5,
"time_down_event": {
"event": "wiki:unfreeze_event",
"target": "self"
}
}
}
},
"components": {
"minecraft:physics": {},
"minecraft:collision_box": {
"width": 0.6,
"height": 1.9
},
"minecraft:movement.basic": {},
"minecraft:navigation.walk": {
"can_path_over_water": true
},
"minecraft:lookat": {
"search_radius": 32.0,
"set_target": false,
"look_cooldown": [0.1, 0.2],
"filters": {
"all_of": [
{
"test": "is_family",
"subject": "other",
"value": "player"
},
{
"test": "has_equipment",
"subject": "other",
"domain": "head",
"operator": "not",
"value": "minecraft:carved_pumpkin"
}
]
},
"looked_at_event": {
"event": "wiki:freeze_event",
"target": "self"
}
}
},
"events": {
"minecraft:entity_spawned": {
"add": {
"component_groups": [
"wiki:moving_state"
]
}
},
"wiki:freeze_event": {
"remove": {
"component_groups": [
"wiki:moving_state"
]
},
"add": {
"component_groups": [
"wiki:frozen_state"
]
}
},
"wiki:unfreeze_event": {
"remove": {
"component_groups": [
"wiki:frozen_state"
]
},
"add": {
"component_groups": [
"wiki:moving_state"
]
}
}
}
}
}Precise Raycasting with the Script API
When you need exact hit detection over long distances, or when you need to know the exact block coordinate a player is looking at, use the `@minecraft/server` Script API. The `Entity` class (which includes `Player`) exposes two dedicated raycast methods: `getEntitiesFromViewDirection()` and `getBlockFromViewDirection()`. Both cast a mathematical ray directly from the entity's camera vector and check against true bounding boxes rather than foot origins.
`getEntitiesFromViewDirection(options)` returns an array of `EntityRaycastHit` objects ordered from closest to furthest. Each hit contains a reference to the `entity` and the `distance` in blocks from the observer's eyes. If a solid block sits between the player and an entity, the method automatically stops the ray at the wall unless you configure `ignoreBlockCollision: true` in the options object.
`getBlockFromViewDirection(options)` returns a single `BlockRaycastHit` object (or `undefined` if looking at the sky or beyond `maxDistance`). This object gives you the `block` instance, the `face` of the block that was struck (such as `Direction.Up` or `Direction.North`), and the `faceLocation` offset. You can pass options like `includeLiquidBlocks` and `includePassableBlocks` to control whether water or tall grass catches the ray.
| Raycast Option | Applies To | What It Controls |
|---|---|---|
| maxDistance | Block & Entity | Maximum distance in blocks the ray travels before returning nothing. |
| ignoreBlockCollision | Entity Raycast | When true, detects entities even if solid walls block the line of sight. |
| includeLiquidBlocks | Block Raycast | When true, water and lava stop the ray instead of letting it pass through. |
| includePassableBlocks | Block Raycast | When true, blocks without collision boxes (like tall grass or torches) stop the ray. |
import { world, system } from "@minecraft/server";
// Run a look check every 5 ticks (4 times per second)
system.runInterval(() => {
for (const player of world.getAllPlayers()) {
// 1. Check for entities in the player's crosshair up to 16 blocks away
const entityHits = player.getEntitiesFromViewDirection({
maxDistance: 16,
ignoreBlockCollision: false
});
if (entityHits.length > 0) {
const closestHit = entityHits[0];
const dist = closestHit.distance.toFixed(1);
player.onScreenDisplay.setActionBar(
`Looking at Entity: ${closestHit.entity.typeId} (${dist}m)`
);
continue;
}
// 2. If no entity was hit, check which block the player is looking at
const blockHit = player.getBlockFromViewDirection({
maxDistance: 8,
includeLiquidBlocks: false,
includePassableBlocks: false
});
if (blockHit) {
player.onScreenDisplay.setActionBar(
`Looking at Block: ${blockHit.block.typeId} (Face: ${blockHit.face})`
);
}
}
}, 5);Which versions this applies to
Applies to Minecraft Bedrock 1.19.50 and newer (current `execute` syntax). `minecraft:lookat` and selector arguments require no experimental toggles. The Script API raycast methods (`getEntitiesFromViewDirection` and `getBlockFromViewDirection`) are part of the stable `@minecraft/server` module (version `1.8.0` and above) and do not require the Beta APIs toggle.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Command raycast with `^ ^ ^` triggers when looking at the floor below a mob, or misses when looking at its head. | You omitted `anchored eyes` in your `/execute` chain, causing `^ ^ ^` to project from the player's feet. Alternatively, your `r=` selector radius is checking against the target mob's feet origin while your ray is passing through its upper body. | Always place `anchored eyes` before `positioned ^ ^ ^distance`, and either increase the radius (`r=1.2`) or step down slightly (`positioned ~ ~-0.8 ~`) before running the `@e[r=...]` selector. |
| Syntax error: `Selector argument 'rx' cannot be less than 'rxm'` (or selector returns zero players when checking upward pitch). | Looking upward uses negative pitch values (`-90` is straight up). Creators frequently write `[rxm=-45,rx=-90]` thinking `-90` is the higher number, but `-90` is mathematically smaller than `-45`. | Always put the more negative number in the minimum argument (`rxm` or `rym`) and the less negative or positive number in the maximum argument (`rx` or `ry`), such as `@a[rxm=-90,rx=-45]`. |
| A custom entity with `minecraft:lookat` freezes once when looked at, and then stays permanently frozen even after the player walks away. | `minecraft:lookat` only includes a `looked_at_event` trigger; it does not have a built-in "stopped looking" event to undo component changes when the player turns away. | Place a short, non-looping `minecraft:timer` inside the component group that `looked_at_event` adds. While the player continues looking, `minecraft:lookat` re-triggers and resets the state; when they look away, the timer finishes and fires an event to remove the frozen component group. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
