Skip to content

Gizmos:即时模式画线

Gizmos 是 Bevy 内置的调试绘图系统——你写一个系统、拿到 Gizmos 系统参数、调方法画线,下一帧线就出现在屏幕上,再下一帧就没了。这就是"即时模式"(immediate mode):每帧重新提交,不存状态。

它不需要加载模型、不需要材质、不需要 UV——只要一行代码,一条线就出来了。适合做碰撞体可视化、路径调试、射线检测显示、坐标轴指示等一切"开发时才看得到、发布时自动消失"的辅助画面。

第一条线

rust
gizmos.line(Vec3::ZERO, Vec3::new(2., 1., 0.), Color::WHITE);

Gizmos 是一个系统参数,和 QueryRes 一样直接出现在函数签名里。line 接受起点、终点和颜色。颜色可以是 Color::WHITEColor::srgb(...),也可以是 bevy::color::palettes::css 里的常量。

球、箭头、射线

Gizmos 提供了丰富的图元方法:

rust
gizmos.sphere(Vec3::new(-2., 1., 0.), 0.8, Color::srgb(0.9, 0.3, 0.3));

sphere 画一个线框球,参数是中心、半径和颜色。默认 32 段线段,调 .resolution(n) 可以改。

rust
gizmos.arrow(
        Vec3::new(0., 0.1, 0.),
        Vec3::new(ops::cos(t) * 2., 1.5, ops::sin(t) * 2.),
        Color::srgb(0.2, 0.8, 0.2),
    );

arrow 画带箭头的线段,从起点指向终点。箭头方向自动推算——非常适合可视化朝向、力的方向。

rust
gizmos.ray(
        Vec3::new(2., 0.5, 0.),
        Vec3::new(-1., ops::sin(t * 2.) * 0.5, 0.),
        Color::srgb(0.3, 0.5, 0.9),
    );

rayarrow 类似,但第二个参数是方向向量而非终点——射线从起点沿方向无限延伸(视觉上是一段足够长的线)。这个例子让方向随时间摆动,你可以直观看到"方向向量"和"终点位置"的区别。

网格参考线

rust
gizmos.grid(
        Quat::from_rotation_x(PI / 2.),
        UVec2::splat(10),
        Vec2::splat(1.),
        Color::srgb(0.25, 0.25, 0.25),
    );

grid 画一个平面网格,参数依次是旋转(四元数)、行列数、格子间距和颜色。把旋转设为绕 X 轴 90° 就是一个水平地面参考网格。对于需要对齐物体摆放的场景非常实用。

完整示例

rust
use bevy::prelude::*;
use std::f32::consts::PI;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, draw_gizmos)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(0., 2.5, 6.).looking_at(Vec3::ZERO, Vec3::Y),
    ));
    commands.spawn((
        PointLight::default(),
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));
}

fn draw_gizmos(mut gizmos: Gizmos, time: Res<Time>) {
    let t = time.elapsed_secs();

    // ANCHOR: line
    gizmos.line(Vec3::ZERO, Vec3::new(2., 1., 0.), Color::WHITE);
    // ANCHOR_END: line

    // ANCHOR: sphere
    gizmos.sphere(Vec3::new(-2., 1., 0.), 0.8, Color::srgb(0.9, 0.3, 0.3));
    // ANCHOR_END: sphere

    // ANCHOR: arrow
    gizmos.arrow(
        Vec3::new(0., 0.1, 0.),
        Vec3::new(ops::cos(t) * 2., 1.5, ops::sin(t) * 2.),
        Color::srgb(0.2, 0.8, 0.2),
    );
    // ANCHOR_END: arrow

    // ANCHOR: ray
    gizmos.ray(
        Vec3::new(2., 0.5, 0.),
        Vec3::new(-1., ops::sin(t * 2.) * 0.5, 0.),
        Color::srgb(0.3, 0.5, 0.9),
    );
    // ANCHOR_END: ray

    // ANCHOR: grid
    gizmos.grid(
        Quat::from_rotation_x(PI / 2.),
        UVec2::splat(10),
        Vec2::splat(1.),
        Color::srgb(0.25, 0.25, 0.25),
    );
    // ANCHOR_END: grid
}

Listing 27-1:基础 Gizmos——线、球、箭头、射线、网格

运行:

console
cargo run -p ch27-devtools --example listing-27-01

你会看到一个 3D 场景:一条白线、一个红球、一支随时间旋转的绿箭头、一条摆动的蓝射线,以及铺在地面上的灰色网格。箭头和射线每帧更新位置——因为 Gizmos 是即时模式,每帧重新画就是"动起来"的全部秘密。

2D 与 3D 的分野

Gizmos 同时支持 2D 和 3D,方法名带 _2d 后缀的是 2D 版本:

3D 方法2D 方法说明
lineline_2d线段
rayray_2d射线
rectrect_2d矩形
circlecircle_2d
arrowarrow_2d箭头

2D 版本接受 Vec2 而非 Vec3,绘制在 2D 相机的平面上。下一节会把 2D 和 3D 图元放在一起展示。