bevy examples
bevy examples
- bevy 栈太深了,system 是并行的,ECS 是非常复杂的模板
bevy ECS
Monday, December 12, 2022
3:08 PM
范式 | 代码示例 | 描述 |
---|---|---|
OOP | if A impl Moveable then A.Move(self.Pos, self.Vel) end | 在执行移动之前,需要检查对象是否具有位置(Pos)和速度(Vel)组件。 |
ECS | foreach Entity with Pos and Vel do Move(Entity) end | 在ECS中,不需要进行组件检查,因为查询系统只返回具有指定组件的实体。 |
其实就是模式匹配,当筛选条件足够复杂时,ECS 保持代码清晰,不需要 ifelse check
何为复杂,就是组件的复杂组合,比如 C1 & C2 | C3,上限就是真正的数据库查询,需要专门的query语言SQL query 完了拿到数据再去使用
第二是,这种范式写的代码更加健壮和容易维护
因为每次都是动态查询,不容易漏
EC的做法就是check C,然后缓存C,这种容易break
每次都全量查询刷新,保证正确
而ECS底层的DOD确保了查询非常快(虽然比缓存慢),这个权衡的收益是正的
hello world
fn main() {
App::new().add_systems(Update, hello_world_system).run();
}
fn hello_world_system() {
println!("hello world");
}
3d scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// circular base
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
..default()
});
// light
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
breakout
-
好歹是个完整游戏,有增删查改,模拟和 UI、音效
-
setup 把所有东西都预先 spawn 好
-
这是 AxB 个 brick
-
spawn bundle 就是 spawn entity
-
bundle 这里是个临时的类型 tuple,brick 和 collider 是 tag
-
collided sfx,类似 event queue 的设计
-
sfx asset 提前加载,存个 handle,这里再 query 出来,这里用 resource 其实就是单例
#[derive(Resource, Deref)]
struct CollisionSound(Handle<AudioSource>);
#[derive(Event, Default)]
struct CollisionEvent;
let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
commands.insert_resource(CollisionSound(ball_collision_sound));
mut collision_events: EventWriter<CollisionEvent>,
collision_events.send_default();
fn play_collision_sound(
mut commands: Commands,
mut collision_events: EventReader<CollisionEvent>,
sound: Res<CollisionSound>,
) {
// Play a sound once per frame if a collision occurred.
if !collision_events.is_empty() {
// This prevents events staying active on the next frame.
collision_events.clear();
commands.spawn(AudioBundle {
source: sound.clone(),
// auto-despawn the entity when playback finishes
settings: PlaybackSettings::DESPAWN,
});
}
}
- input->move paddle transform,逻辑很简单
- system 的参数就是函数的输入输出,等系统检测到有这个 pattern 的 input 就调用这个 system 来处理
- input、time 是单例
- mut query: Query<&mut Transform, With>,就是获取 paddle 的 transform(可写)
- ECS 的 data 中,component 是基本单位,bundle 是可嵌套的文件夹,方便整理,实际 entity 有这么些 components,query 时是 flat 的
- sprite bundle 是渲染对象,有位置组件,直接更新这个
commands.spawn((
SpriteBundle {
transform: Transform {
translation: Vec3::new(0.0, paddle_y, 0.0),
scale: PADDLE_SIZE.extend(1.0),
..default()
},
sprite: Sprite {
color: PADDLE_COLOR,
..default()
},
..default()
},
Paddle,
Collider,
));
fn move_paddle(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut query: Query<&mut Transform, With<Paddle>>,
time: Res<Time>,
) {
let mut paddle_transform = query.single_mut();
let mut direction = 0.0;
if keyboard_input.pressed(KeyCode::ArrowLeft) {
direction -= 1.0;
}
if keyboard_input.pressed(KeyCode::ArrowRight) {
direction += 1.0;
}
// Calculate the new horizontal paddle position based on player input
let new_paddle_position =
paddle_transform.translation.x + direction * PADDLE_SPEED * time.delta_seconds();
// Update the paddle position,
// making sure it doesn't cause the paddle to leave the arena
let left_bound = LEFT_WALL + WALL_THICKNESS / 2.0 + PADDLE_SIZE.x / 2.0 + PADDLE_PADDING;
let right_bound = RIGHT_WALL - WALL_THICKNESS / 2.0 - PADDLE_SIZE.x / 2.0 - PADDLE_PADDING;
paddle_transform.translation.x = new_paddle_position.clamp(left_bound, right_bound);
}
- 速度积分
fn apply_velocity(mut query: Query<(&mut Transform, &Velocity)>, time: Res<Time>) {
for (mut transform, velocity) in &mut query {
transform.translation.x += velocity.x * time.delta_seconds();
transform.translation.y += velocity.y * time.delta_seconds();
}
}
原文地址:https://blog.csdn.net/zolo_mario/article/details/142756062
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!