🔦 射线追踪(Raycast)#

#bs.raycast:help

检测射线与方块或实体的碰撞。

“现实只有在诗歌之光的照耀下才会展现自己。”

—乔治·布拉克(Georges Braque)

Looking for simple use cases?

If you just want to detect what an entity is looking at (aimed block, aimed entity, hit point), the View module provides simplified wrappers that handle the common cases for you.

How does it work?

This module uses a voxel traversal algorithm. Instead of checking points at fixed intervals, the ray steps from one block boundary to the next, ensuring every block is checked without redundant operations.


🔧 函数#

你可以在下方找到此模块中的所有可用函数。


Run#

#bs.raycast:run {with:{}}

在执行位置发射一条射线并检查它的碰撞情况。

输入:

Execution at <entity> or positioned <x> <y> <z> rotated <rot>: origin of the ray

函数宏

  • arguments

    • with: ray input data

      • blocks: whether the ray stops on blocks (default: true)

        Can be a hitbox provider (e.g. function #bs.hitbox:callback/get_block_collision).

      • entities: whether the ray stops on entities (default: false)

        Can be a selector tag (typically assigned via /tag), which is preferred for performance.

      • ignored_blocks: blocks to ignore (default: #bs.hitbox:intangible)

      • ignored_entities: entity types to ignore (default: #bs.hitbox:intangible)

        Does not apply to entities with custom hitboxes.

      • max_distance: maximum ray travel distance (default: 16.0)

      • on_targeted_block: callback to run at the targeted block (aligned)

      • on_targeted_entity: callback to run as and at the targeted entity

      • on_entry_point: callback to run at the point where the ray enters a shape

        May run multiple times per block with complex shapes and piercing.

      • on_exit_point: callback to run at the point where the ray exits a shape

        May run multiple times per block with complex shapes and piercing.

      • piercing: blocks or entities the ray can pass through (default: 0)

        • blocks: blocks to track independently from entities (default: 0)

        • entities: entities to track independently from blocks (default: 0)

Lambda 函数:

Score $raycast.entry_distance bs.lambda: distance from origin to the entry point (×1000)

Score $raycast.exit_distance bs.lambda: distance from origin to the exit point (×1000)

Score $raycast.prev_entry_distance bs.lambda: entry distance from the previous hit (×1000)

Score $raycast.prev_exit_distance bs.lambda: exit distance from the previous hit (×1000)

Score $raycast.hit_face bs.lambda: entry face of the bounding box, 5 is east, 4 is west, 3 is south, 2 is north, 1 is top, and 0 is bottom

Score $raycast.hit_flag bs.lambda: flag of the intersected bounding box, -1 for entities

Score $raycast.piercing bs.lambda: remaining number of blocks or entities the ray can pass through

Scores $raycast.entry_point.[x,y,z] bs.lambda: entry point relative to the block or entity (×1000)

Scores $raycast.exit_point.[x,y,z] bs.lambda: exit point relative to the block or entity (×1000)

Scores $raycast.targeted_block.[x,y,z] bs.lambda: coordinates of the targeted block

输出:

Return: whether the ray collides with a hitbox or not (1 or 0)

What is a bounding box?

A bounding box is a rectangular box that surrounds an object—or part of it—to detect where it is and what it touches. For example, stairs use two bounding boxes: one for the lower step and one for the upper step.

Custom hitboxes

Bookshelf supports multiple hitbox types for precise control. Blocks can use custom hitbox providers. Entities support dynamic, baked, and custom types.

制作人员:Aksiome


🎓 How to use#

Basic raycast#

At its simplest, a raycast checks if something is in front of you and returns 1 (hit) or 0 (miss):

# Check if there's a block within 10 blocks in front of you
execute anchored eyes positioned ^ ^ ^ store result score #hit bs.data run function #bs.raycast:run {with:{max_distance:10}}

By default, rays detect blocks but not entities. The return value tells you if a collision occurred.


Using callbacks#

Callbacks let you run commands when the ray hits something. There are four callback types:

Callback

Runs at

Use case

on_targeted_block

Aligned block position

Place/break blocks, check block type

on_targeted_entity

Entity position (as & at)

Damage, tag, or interact with entity

on_entry_point

Exact point where ray enters

Spawn particles, precise hit effects

on_exit_point

Exact point where ray exits

Through-hit effects, exit wounds

Example: spawn a particle exactly where your ray hits a block

execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{on_entry_point:"particle minecraft:flame ~ ~ ~"}}

Configuring detection#

By default, rays detect blocks but not entities. You can change this with the blocks and entities parameters.

Blocks accepts true (default), false, or a hitbox provider.

# Ignore blocks entirely
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{blocks:false,entities:true,on_targeted_entity:"say Hit!"}}

Entities accepts true, false (default), or an entity tag to filter which entities can be hit.

# Detect all entities
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{entities:true,on_targeted_entity:"say I was hit!"}}

# Detect only entities with a specific tag (better performance)
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{entities:"my_tag",on_targeted_entity:"say I was hit!"}}

小技巧

Using a tag selector (entities:"my_tag") is more performant than entities:true because it narrows down which entities to check.


Filtering targets#

Use ignored_blocks and ignored_entities to specify which targets the ray should skip:

# Ignore glass blocks
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{ignored_blocks:"#c:glass_blocks",on_targeted_block:"setblock ~ ~ ~ stone"}}

# Ignore specific entity types
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{entities:true,ignored_entities:"#bs.hitbox:intangible",on_targeted_entity:"say Hit!"}}

Defaults:

  • ignored_blocks: #bs.hitbox:intangible (blocks that cannot be physically interacted with)

  • ignored_entities: #bs.hitbox:intangible (entities that don’t act as physical obstacles)


Piercing#

By default, rays stop at the first collision. Use piercing to let rays pass through multiple targets:

# Pass through up to 3 blocks before stopping
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{piercing:3,on_entry_point:"particle minecraft:flame ~ ~ ~"}}

You can also track blocks and entities separately:

# Pass through 2 blocks but stop at first entity
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{entities:true,piercing:{blocks:2,entities:0},on_entry_point:"particle minecraft:flame ~ ~ ~"}}

Lambda scores#

Lambda scores provide detailed information about the collision, available only inside callbacks. See the function reference above for the full list.

Common use cases:

  • $raycast.entry_distance - how far the hit is from the ray origin

  • $raycast.entry_point.[x,y,z] - exact hit position relative to the target

  • $raycast.hit_face - which face was hit (0=bottom, 1=top, 2=north, 3=south, 4=west, 5=east)

  • $raycast.hit_flag - which hitbox shape was hit (provider-dependent, -1 for entities)

重要

Position scores (entry_point, exit_point) have different reference points:

  • Blocks: relative to the aligned block position

  • Entities: relative to the entity’s position


Hitbox providers#

Hitbox providers control which block shapes the ray detects. The default only detects solid collision shapes, but you can use other providers to detect additional shapes like fluids.

# Detect both solid blocks and fluids
execute anchored eyes positioned ^ ^ ^ run function #bs.raycast:run {with:{blocks:"function #bs.hitbox:callback/get_block_shape_with_fluid",ignored_blocks:"#air"}}

Providers can define multiple shapes with different flags. When this happens:

  • on_targeted_block runs once per block, with $raycast.hit_flag combining all intersected shapes

  • on_entry_point and on_exit_point run once per shape, with $raycast.hit_flag set to that shape’s flag

For example, the fluid provider uses 1 for solid and 2 for fluid. A waterlogged block could trigger entry/exit callbacks twice (with flag 1 and 2), and on_targeted_block once with flag 3.


💬 这对你有帮助吗?

欢迎在下方留下你的问题和反馈!