Latest commit 789b9ee
变换
相关的官方文档:[transform]、[translation]、[rotation]、[3d_rotation]、[scale]、[move_sprite]、[parenting]
变换使得游戏物体能够被放置在游戏世界中。物体的“平移”(位置/坐标)、“旋转”和“比例”(大小调整)的组合就是变换:
- 平移:移动物体
- 旋转:旋转物体
- 比例:放大或缩小物体
#![allow(unused)] fn main() { // 平移 let xf_pos567 = Transform::from_xyz(5.0, 6.0, 7.0); // 缩放 let xf_scale = Transform::from_scale(Vec3::splat(2.0)); // 旋转 2d 物体(绕 Z 轴旋转) 30° let xf_rot2d = Transform::from_rotation(Quat::from_rotation_z(30.0_f32).to_radians()) // 3d 旋转 --- 略 // 变换 let xf = Transform::from_xyz(1.0, 2.0, 3.0) .with_scale(Vec3::new(0.5, 0.5, 1.0)) .with_rotation(Quat::from_rotation_y(0.125 * std::f32::conts::PI)); }
变换组件
在 Bevy 中,变换由两个组件表示:Transform 和 GlobalTransform。如果某个实体表示的是游戏世界中的物体,那么这个实体必须同时拥有 Transform 和 GlobalTransform。
所有 Bevy 内置的 Bundle 类型都包含 Transform 和 GlobalTransform。自定义 Bundle
类型可以添加这些 Bundle 来确保包含 Trasform 和 GlobalTransform:
- SpatialBundle:transform + visibility
- TransformBundle:transform
#![allow(unused)] fn main() { fn 生成特殊实体( mut commands: Commands, ) { // 创建一个实体,不使用内置包,但需要 transform 和 visibility 功能 commands.spawn() .insert(ComponentA) .insert(ComponentB) .insert_bundle(SpatialBundle { transform: Transform::from_scale(Vec3::splat(3.0)), visibility: Visibility { is_visible: false, }, }); } }
Transform 组件
Transform 最常用,是一个包含平移、旋转和缩放的结构体。要读取或操作这些值,请在系统中用 Query 来访问。
如果实体有父实体,Transform 组件是相对于父实体的。这意味着子实体会与父实体一起移动/旋转/缩放。
#![allow(unused)] fn main() { fn 给气球打气 ( mut query: Query<&mut Transform, With<Balloon>>, keyboard: Res<Input<KeyCode>>, ) { // 每次按下空格键,所有气球扩大 25% if keyboard.just_pressed(KeyCode::Space) { for mut transform in &mut query { transform.scale *= 1.25; } } } }
GlobalTransform 组件
GlobalTransform 表示世界中的绝对全局位置。如果实体没有父实体,那么这个值和 Transform 相同。GlobalTransform 的值是由 Bevy 内部计算/管理的,视为只读数据,不要进行可变修改。
变换传播
注意:Transform 和 GlobalTransform 的同步是由运行在 PostUpdate 阶段的内部系统(“变换传播系统”)管理的,如果手动修改 Transform,GlobalTransform 不会立即更新。也就是:在当前帧里更新 Transform 后立即获取 GlobalTransform 的数值,GlobalTransform 不变,要等到下一帧才能获取正确的 GlobalTransform。
如果要立即处理 GlobalTransform,必须把系统放在 PostUpdate 阶段,并用标签让系统跟在 TransformSystem::TransformPropagate 后面运行。
/// 打印“当前帧”的最新全局位置 fn 调试全局变换( query: Query<&GlobalTransform, With<Player>>, ) { let gxf = query.single(); debug!("玩家位于:{:?}", gxf.translation()); } fn main() { use bevy::transform::TransformSystem; App::new() .add_plugins(DefaultPlugins) .add_system_to_stage( CoreStage::PostUpdate, 调试全局变换.after(TransformSystem::TransformPropagete) ) .run(); }