用途
当一套 2D 设计需要获得 3D 相机与网格时加载本技能。核心思路是保留玩法组件,只替换相机与可绘制对象。
主要能力
- 将角色实体上的 Sprite 替换为 Mesh3d 与 MeshMaterial3d。
- 将相机实体上的 Camera2d 替换为 Camera3d 与透视 Projection。
- 将平面运动数据从 Vec2 velocity 提升为 XZ 平面上的 Vec3 wish。
- 保留角色上的玩法组件不变。
变更对照
保留:角色上的玩法组件、相机实体、作为数据的平面运动。
替换:Sprite → Mesh3d 与 MeshMaterial3d;Camera2d → Camera3d 与透视 Projection;Vec2 velocity → XZ 上的 Vec3 wish。
使用方式
没有转换辅助函数。通过一个启动系统重写已经生成的实体。物理求解器仍留在物理相关技能中。
依赖声明:
[dependencies]
bevy = "0.20"
示例代码(保留原样):
use bevy::mesh::Meshable;
#[derive(Component)]
struct Actor;
#[derive(Component)]
struct PlanarVelocity(Vec2);
#[derive(Component)]
struct WishVelocity(Vec3);
fn promote_actors(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
actors: Query<(Entity, &Transform), (With<Actor>, With<Sprite>)>,
) {
let mesh = meshes.add(Cuboid::new(0.8, 1.6, 0.8).mesh());
let material = materials.add(StandardMaterial {
base_color: Color::srgb(0.75, 0.45, 0.25),
..default()
});
for (entity, transform) in &actors {
let ground = Vec3::new(transform.translation.x, 0.8, transform.translation.y);
commands.entity(entity).remove::<Sprite>().insert((
Mesh3d(mesh.clone()),
MeshMaterial3d(material.clone()),
Transform::from_translation(ground),
));
}
}
fn promote_camera(mut commands: Commands, cameras: Query<Entity, With<Camera2d>>) {
for entity in &cameras {
commands.entity(entity).remove::<Camera2d>().insert((
Camera3d::default(),
Projection::Perspective(PerspectiveProjection::default()),
Transform::from_xyz(0.0, 6.0, 12.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}
}
fn lift_velocity(mut actors: Query<(&PlanarVelocity, &mut WishVelocity), With<Actor>>) {
for (planar, mut wish) in &mut actors {
wish.0 = Vec3::new(planar.0.x, 0.0, planar.0.y);
}
}
pub struct AdaptTo3dPlugin;
impl Plugin for AdaptTo3dPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, (promote_actors, promote_camera).chain())
.add_systems(FixedUpdate, lift_velocity);
}
}
fn spawn_follow_camera(mut commands: Commands) {
commands.spawn((
Camera3d::default(),
Projection::Perspective(PerspectiveProjection {
fov: 50.0_f32.to_radians(),
..default()
}),
Transform::from_xyz(0.0, 4.0, 8.0).looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
));
}
专家知识要点
目标:Bevy 0.20+。
核心 ECS 类型:Component、Resource、Query、Commands、Startup、Update、Fixed / FixedMain(bevy::time)、.chain()、Plugin、DefaultPlugins、MinimalPlugins。消息与观察者属于所有权槽位,其 API 参见 bevy-events-messaging。除非用 .chain() 对冲突系统排序,否则系统并行运行。
状态所有权:
- 单个实体上的数据:Component,由某个系统通过 Query 修改,运行于 Update 或 FixedMain。
- 整个应用共享的一个值:Resource,由某个系统修改,在 Startup 插入,之后由读取它的调度使用。
- 生成:Commands,由生成系统负责,Startup 用于初始世界,后续调度用于运行时生成。
- 不能竞态的顺序:.chain(),仅作用于被链式连接的系统,位于同一调度内。
- 插件边界:Plugin,build 注册系统与资源,在应用运行前完成。
借用规则:两个系统若都可变查询同一组件,必须排序(.chain())或拆分,使只有一个写入。无关系统保持并行。这是 ECS 页面规则,不是对系统集 API 的猜测。
决策表:
- 需要逐实体数据:用 Component + Query;不要用一个脚本拥有整个角色。
- 需要应用级配置或时钟:用 Resource;不要把值复制到每个实体。
- 需要稳定仿真步长:用 FixedMain 与 Fixed 时钟;不要把仿真绑定到原始帧 Update。
- 需要启动生成:在 Startup 中用 Commands;不要从渲染系统生成。
- 需要非共享状态的跨系统通知:使用 bevy-events-messaging 中的消息或观察者槽位;不要在本文件中发明新事件类型。
- 需要文档集之外的 API:先查官方文档;不要使用编造的 crate 或 API。
加载 references/ecs-ownership.md 可查看所有权表。
禁止事项
- 不要在文档 URL 中固定 /0.20.0/。原因:链接保持指向最新版;0.20 目标只在正文中声明一次。
- 不要从两个无序系统可变查询同一组件。原因:除非用 .chain() 排序,调度会并行运行系统。
- 不要在此发明物理、导航、网络或 XR crate。原因:本技能只命名有文档记录的 Bevy crate 与模块。
- 不要使用来自其他引擎的节点 convert-to-3D 操作。原因:Bevy 没有场景树转换;启动系统会在同一实体上移除 Sprite 并插入网格组件。
- 不要在 Bevy 代码中使用外部引擎类型。原因:Camera3d 与 Mesh3d 是该调度已运行的绘制路径。
- 不要发明 API 或把未命名的第三方 crate 作为选定求解器。原因:Bevy 代码保持惯用 ECS,只使用有文档记录的 Bevy API。
参考
bevy-master 上的库固定版本保持 0.20.0。当某个系统既移除 2D 组件又写入速度时,加载 references/ecs-ownership.md。不要为编写材质而加载它。
官方文档:
- Assets - 官方资产目录。未选择第三方 crate。
- Examples - 最新分支上的示例树。
- ECS - Component、systems、Query、Startup、Update 与 .chain()。
- Plugins - Plugin、DefaultPlugins、MinimalPlugins 与 add_plugins。
相关技能
前置:bevy-master(枢纽与调度)、bevy-ecs-composition(组件与系统)、bevy-camera-systems(Camera2d 与 Camera3d)、bevy-3d-world-building(关卡组装)。
互补:bevy-adapt-3d-to-2d(反向适配)。
下游 / 消费者:暂无。
主技能:bevy-master(Bevy 路由)。
适用场景与限制
适用:Bevy 2D 游戏需要引入透视相机与 3D 网格,同时保留玩法组件。
限制:不提供转换辅助函数;不涉及物理、导航、网络或 XR crate;不使用其他引擎的转换操作;仅使用有文档记录的 Bevy API;目标版本 Bevy 0.20+。