Rust Bevy 0.13 到 0.14 升级踩坑指南
重要提醒本文记录将一个 Bevy 0.13 的 2D 像素游戏升级到 0.14 版本的全过程踩坑记录。0.14 是作者在 macOS 上运行最稳定的版本更高版本会出现黑屏问题因此锁定此版本。升级后还顺手将项目中从 Python 迁移过来的两个模块调试控制台和剧本系统进行了补充。一、为什么是 0.14macOS 兼容性0.15 及以上版本在 macOS 上存在黑屏问题0.14 是目前最稳定的选择。破坏性变更0.13 → 0.14 存在破坏性 API 变更不能仅仅修改 Cargo.toml 中的版本号。二、Cargo.toml 的三处改动1. 版本号# before bevy { version 0.13, default-features false, features [...] } after bevy { version 0.14, default-features false, features [...] }2. feature 名改了下划线大小写# 0.13 用 hyphen-case multi-threaded, 0.14 改成 snake_case multi_threaded,运行cargo fetch会直接报错package depends on bevy with feature multi-threaded but bevy does not have that feature. help: there is a feature multi_threaded with a similar name按照提示修改即可。3. 诊断插件 feature 改了名# 0.13 bevy_diagnostic, # ❌ 0.14 没这个 feature 0.14 bevy_dev_tools, # ✅ FrameTimeDiagnosticsPlugin 跟着这个来报错会列出全部可用 feature从里面挑选即可。4. 显式加 bevy_state / bevy_app 依赖这是default-features false项目的专属坑——详见下一节。三、State API最大的坑症状升级后一编译就刷出一屏幕错误error: cannot find derive macro States in this scope error[E0425]: cannot find type NextState in this scope error[E0425]: cannot find function in_state in this scope error[E0425]: cannot find OnEnter / OnExit error[E0599]: no method named init_state found for mut App error[E0599]: no method named enable_state found for mut App根因0.14 把 state 系统移出了bevy::prelude迁移到了独立的 cratebevy_state。bevy通过bevy_internal重命名 re-export// bevy_internal/src/lib.rs #[cfg(feature bevy_state)] pub use bevy_state as state;所以bevy::state这条路径理论上还在但需要开启bevy_statefeature。而我们使用了default-features false默认的 feature 集被砍掉了——0.13 时 state 跟着 prelude 走0.14 必须显式开启。解法三步第一步Cargo.toml 开 feature 加依赖bevy { version 0.14, default-features false, features [ ..., bevy_state, # 激活 bevy::state re-export ] } 单开 bevy_state feature 还不够AppExtStates含 init_state在 bevy_state::app 里 它 use bevy_app::{App, ...}。所以要把 bevy_app 也拉进依赖图。 bevy_state 0.14 bevy_app 0.14第二步import 路径全部改走bevy_state// ❌ 0.13靠 prelude 自动可用 #[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum GameState { ... } .add_systems(OnEnter(GameState::Playing), ...) .add_systems(Update, foo.run_if(in_state(GameState::Playing))) .next_state.set(GameState::GameOver);// ✅ 0.14全部 explicit import use bevy_state::app::AppExtStates; // 含 init_state use bevy_state::state::{OnEnter, OnExit, States, NextState}; use bevy_state::condition::in_state;每个用到NextState的文件都要加一行use bevy_state::state::NextState;第三步删掉enable_state调用// ❌ 0.13 写法 .init_state::GameState() .enable_state::GameState() // 0.14 砍了这方法// ✅ 0.14init_state 单独够用内部已 setup transitions .init_state::GameState()验证路径是否正确的最小用例升级时我先在/tmp里创建一个小的 cargo 项目验证 import 路径再回主项目修改use bevy::prelude::*; use bevy_state::app::AppExtStates; use bevy_state::state::{OnEnter, OnExit, States, NextState}; use bevy_state::condition::in_state; #[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum S { #[default] A, B } fn main() { App::new() .init_state::S() .add_systems(OnEnter(S::A), || {}) .add_systems(OnExit(S::A), || {}) .add_systems(Update, (|| {}).run_if(in_state(S::A))) .run(); }运行cargo check通过后再回主项目批量修改——比直接在主项目里试错快得多。AppExtStates 的可用方法0.14enable_state被砍掉之后我查阅了bevy_state::app::AppExtStates的完整方法表确认 0.14 只剩这些方法用途init_state::S()初始化一个 State取代 0.13 的 init_state enable_state 组合insert_state::S(state)初始化并设初值add_computed_state::S()计算状态add_sub_state::S()子状态enable_state_scoped_entities::S()state scoped entity 自动清理四、Mesh::from(shape::Circle) 的 shape 模块消失症状error[E0433]: cannot find module or crate shape in this scope根因0.13 的bevy::sprite::shape::Circle { radius, vertices }在 0.14 被移走了。0.14 把几何图元迁移到了bevy_math::primitives且Circle结构体砍掉了vertices字段只剩radius// bevy_math 0.14 pub struct Circle { pub radius: f32, }解法// ❌ 0.13 use bevy::prelude::*; // shape 跟着 prelude 走 let mesh meshes.add(Mesh::from(shape::Circle { radius: 32.0, vertices: 32 })); // ✅ 0.14显式 import 去掉 vertices 字段 use bevy::math::primitives::Circle; let mesh meshes.add(Mesh::from(Circle { radius: 32.0 })); // FromCircle for Mesh 仍存在默认 32 分辨率如果想要自定义分辨率用 builder 链use bevy::math::primitives::Circle; use bevy::render::mesh:: primitives::Meshable; // trait .mesh() let mesh meshes.add(Circle { radius: 32.0 }.mesh().resolution(64).build());五、Color 分量访问.r() .g() .b() .a() 全砍症状error[E0599]: no method named r found for struct Color in the current scope error[E0599]: no method named g found for struct Color in the current scope error[E0599]: no method named b found for struct Color in the current scope error[E0599]: no method named a found for struct Color in the current scope根因0.13 的Color提供了.r(),.g(),.b(),.a()等 getter 方法。0.14 将这些方法全部移除改为直接访问结构体字段。解法// ❌ 0.13 let color Color::rgb(0.5, 0.2, 0.8); let red color.r(); let alpha color.a(); // ✅ 0.14直接访问字段 let color Color::rgb(0.5, 0.2, 0.8); let red color.r; let alpha color.a;注意Color的字段是公开的可以直接读写。六、其他常见变更与修复1. 输入系统KeyCode 枚举成员重命名部分KeyCode枚举成员在 0.14 中被重命名以符合更标准的命名约定。// ❌ 0.13 KeyCode::LControl KeyCode::RControl // ✅ 0.14 KeyCode::ControlLeft KeyCode::ControlRight类似的重命名也适用于其他修饰键Shift, Alt, Meta/Command。编译器会给出明确的错误提示按照提示修改即可。2. 精灵图集TextureAtlas布局 API 变更创建TextureAtlas的 API 有所调整。// ❌ 0.13 let atlas TextureAtlas::from_grid( texture_handle, Vec2::new(16.0, 16.0), 4, 4, None, None, ); // ✅ 0.14 let atlas TextureAtlas::from_grid( texture_handle, Vec2::new(16.0, 16.0), 4, 4, None, None, false, // 新增参数是否填充空白区域 );3. 相机投影CameraProjection相关变更如果使用了自定义相机投影可能需要更新 trait 实现。// ❌ 0.13 impl CameraProjection for MyProjection { fn get_projection_matrix(self) - Mat4 { ... } fn update(mut self, width: f32, height: f32) { ... } fn far(self) - f32 { ... } // ... } // ✅ 0.14 impl CameraProjection for MyProjection { fn get_projection_matrix(self) - Mat4 { ... } fn update(mut self, width: f32, height: f32) { ... } // far 等方法可能已被移除或移至其他 trait请查阅最新文档。 }七、升级后补充模块调试控制台与剧本系统在成功升级到 Bevy 0.14 后我顺手将项目中从 Python 原型迁移过来的两个核心模块进行了 Rust 重写和集成。1. 调试控制台Debug Console一个简单的内嵌式命令行界面用于在游戏运行时执行命令、修改变量、打印状态。// 主要功能 // - 按 键呼出/隐藏控制台 // - 支持基本命令spawn, teleport, godmode, fps // - 命令历史与自动补全 // - 输出日志滚动显示2. 剧本系统Script System一个基于事件的轻量级叙事与任务系统用于驱动游戏剧情和角色对话。// 核心组件 #[derive(Component)] pub struct Script { pub id: String, pub triggers: VecTrigger, pub actions: VecAction, } // 事件驱动 pub struct ScriptEvent { pub script_id: String, pub params: HashMapString, String, }这两个模块的加入显著提升了项目的可调试性和内容创作灵活性。八、总结从 Bevy 0.13 升级到 0.14 主要挑战在于 State API 的抽离和一系列破坏性命名变更。关键步骤总结如下修改 Cargo.toml更新版本号修正 feature 名称如multi_threaded并显式添加bevy_state和bevy_app依赖。重构 State 相关代码将所有States,NextState,OnEnter,OnExit,in_state的导入路径改为bevy_state::*并移除enable_state调用。更新几何图元将shape::Circle等替换为bevy::math::primitives::Circle注意字段变化。修正 Color 访问将.r()等方法调用改为直接字段访问.r。处理其他 API 变更如KeyCode重命名、TextureAtlasAPI 变更等。升级过程虽然繁琐但 0.14 在 macOS 上的稳定性提升是值得的。建议在升级前在一个独立的小项目中验证关键变更再回到主项目进行系统性的修改。