Wiki 9Minecraft Wiki 9Minecraft

Look Detection in Commands, Entities, and Scripts

How to detect when a player or mob looks at an entity, block, or direction using commands, JSON, and Script API.

5Sections
4Code examples
3Known errors

Look detection determines whether a player or mob has their crosshair aimed at a specific target or along a specific compass heading. You reach for these techniques when building weeping-angel monsters that freeze when watched, custom shops that highlight when hovered over, sniper scopes, or puzzle doors that unlock only when the player stares at a symbol. Because Minecraft Bedrock offers four distinct ways to check line of sight—each with different range limits, performance costs, and obstacle-handling rules—choosing the right method depends on whether you are writing quick command functions, designing custom entities, or coding with the Script API.

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.

MethodChecks Obstacles?Best Used For
Selector args (rx, ry)NoChecking if a player looks up at the sky, down at the ground, or toward a compass wall.
Local coordinates (^ ^ ^)Manual onlyCommand-only packs checking if a player aims at an entity within a known, fixed distance.
minecraft:lookat componentYes (Engine LoS)Custom mobs that freeze, aggro, or transform when a player looks directly at them.
Script API RaycastingYes (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.

BP/functions/look_check_fixed.mcfunction
# 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 ArgumentRangeKey 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.090.0 is straight down; 0.0 is horizon.
rym / ry (Yaw)-180.0 to 180.00.0 South, 90.0 West, -90.0 East, 180.0/-180.0 North.
BP/functions/sky_gaze.mcfunction
# 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 ^ ^ ^3

Entity 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.

BP/entities/weeping_statue.json
{
  "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 OptionApplies ToWhat It Controls
maxDistanceBlock & EntityMaximum distance in blocks the ray travels before returning nothing.
ignoreBlockCollisionEntity RaycastWhen true, detects entities even if solid walls block the line of sight.
includeLiquidBlocksBlock RaycastWhen true, water and lava stop the ray instead of letting it pass through.
includePassableBlocksBlock RaycastWhen true, blocks without collision boxes (like tall grass or torches) stop the ray.
BP/scripts/look_detector.js
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 seeWhyThe 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.