0Pricing
Learn Rust Coding · 课时

创建并移动实体

将对象放到屏幕上。

创建并移动实体 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

命令:延迟生成

系统并行运行时,您不能直接修改 World。相反,应当通过 Commands 将结构变化加入队列。

生成实体、销毁实体以及添加组件的操作都会先被记录,并在调度阶段结束时应用,从而保证访问安全。

fn setup(mut commands: Commands) {
    commands.spawn_empty();
}

使用 Bundle 生成实体

Bundle 是一组同时插入的组件。最简单的 Bundle 就是一个组件元组。

Bevy 会将元组中的每个元素视为要附加的组件,因此一次生成调用就能为实体提供全部初始数据。

fn setup(mut commands: Commands) {
    commands.spawn((
        Position { x: 0.0, y: 0.0 },
        Velocity { x: 1.5, y: 0.0 },
        Player,
    ));
}

用于观察世界的摄像机

没有摄像机就不会渲染任何内容。对于 2D 游戏,请在启动系统中生成一个 Camera2d。

摄像机本身也是一个带有摄像机组件的实体,这是 ECS 统一性的又一个例子。场景中的一切都是实体。

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d::default());
}

生成精灵

要绘制某个对象,请为实体添加 Sprite 和 Transform。Transform 保存世界空间中的位置、旋转和缩放。

有颜色的精灵不需要图像资源,这对于在导入美术资源之前制作移动原型非常方便。

commands.spawn((
    Sprite::from_color(Color::srgb(0.2, 0.7, 1.0), Vec2::new(40.0, 40.0)),
    Transform::from_xyz(0.0, 0.0, 0.0),
    Velocity { x: 80.0, y: 0.0 },
));

Transform 与自定义 Position

在真实的 Bevy 游戏中,您通常会移动内置的 Transform,而不是自定义的 Position,因为渲染系统会直接读取 Transform。

平移量是一个 Vec3。对于 2D,您需要修改 x 和 y,并保留 z 用于控制绘制顺序。

#[derive(Component)]
struct Velocity { x: f32, y: f32 }

fn apply_velocity(mut q: Query<(&mut Transform, &Velocity)>) {
    for (mut tf, vel) in &mut q {
        tf.translation.x += vel.x;
        tf.translation.y += vel.y;
    }
}

以可变方式迭代查询

要修改组件数据,请请求 &mut T,并遍历 &mut query。每个元素都会提供可变引用。

Bevy 保证不会同时让两个系统持有互相冲突的可变访问,因此即使其他系统正在运行,这个循环也是安全的。

fn move_all(mut q: Query<&mut Transform, With<Player>>) {
    for mut tf in &mut q {
        tf.translation.x += 1.0;
    }
}

生成多个实体

循环可以让您填充关卡。在 Rust 的 for 循环中调用 spawn,即可创建障碍物网格或敌人群。

每次迭代都会将自己的命令加入队列,所有命令会在阶段边界统一应用。

fn spawn_row(mut commands: Commands) {
    for i in 0..5 {
        commands.spawn((
            Sprite::from_color(Color::WHITE, Vec2::splat(20.0)),
            Transform::from_xyz(i as f32 * 30.0, 0.0, 0.0),
        ));
    }
}

销毁实体

使用 commands.entity(id).despawn() 可以彻底移除实体。这会释放其组件,并回收实体索引。

通常,您会在查询到实体 Entity ID 的系统中销毁实体,例如销毁已经离开屏幕的子弹。

fn cleanup(mut commands: Commands, q: Query<(Entity, &Transform)>) {
    for (e, tf) in &q {
        if tf.translation.y > 600.0 {
            commands.entity(e).despawn();
        }
    }
}

稍后添加组件

运行时可以通过 insert 为现有实体附加新组件。这就是为获得强化的玩家添加 Shield 标签的方式。

移除组件的方式类似,只需使用 remove::<T>()。两者都是结构变化,因此都要通过 Commands 执行。

commands.entity(player).insert(Shield { hits: 3 });
// later
commands.entity(player).remove::<Shield>();

使用 Z 进行分层

在 2D 中,变换平移量的 z 值决定绘制顺序。z 越高,渲染结果越靠上层。

请为背景设置较低的 z,为玩家设置较高的 z,这样精灵就不会消失在场景后面。

// background behind, player in front
commands.spawn((bg_sprite, Transform::from_xyz(0.0, 0.0, 0.0)));
commands.spawn((player_sprite, Transform::from_xyz(0.0, 0.0, 10.0)));

连接各部分

在 Startup 中生成实体,在 Update 中移动实体。启动系统只创建一次摄像机和实体;更新系统则每帧推进它们的状态。

这种分离方式可以避免初始化逻辑进入每帧执行的关键路径。

App::new()
    .add_plugins(DefaultPlugins)
    .add_systems(Startup, setup)
    .add_systems(Update, apply_velocity)
    .run();

快速检查

思考结构变化是如何应用的。

回顾:生成与移动

您可以通过 Commands 使用 Bundle 生成实体,使用 Sprite 和 Transform 渲染实体,并在 Update 系统中修改变换来移动实体。

销毁实体和插入组件也都是命令。接下来,我们将让移动响应键盘输入和实际经过的时间。

常见问题解答

「创建并移动实体」课时是免费的吗?

是的 — 「创建并移动实体」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「创建并移动实体」这节课中我会学到什么?

将对象放到屏幕上。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「创建并移动实体」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. ECS 思维方式
  2. 创建并移动实体
  3. 处理输入和时间
  4. 碰撞和游戏状态
← 返回 Learn Rust Coding