使用Bevy渲染棋盘格出现空白屏问题求助
在Bevy中渲染棋盘格时遇到空白屏问题
我正在尝试用Bevy渲染棋盘格(或搭建通用网格系统),但屏幕始终显示一片灰色,完全看不到棋盘格效果。
实现代码
Grid组件定义
#[derive(Debug, Component)] /// 定义单个网格单元 /// 因`Cell`在Rust中有特定术语含义,故用Grid指代 pub(crate) struct Grid(u8, u8); impl Grid { pub(crate) fn new(x: u8, y: u8) -> Self { Self(x, y) } pub(crate) fn x(&self) -> u8 { self.0 } pub(crate) fn y(&self) -> u8 { self.1 } pub(crate) fn indices(&self) -> (u8, u8) { (self.x(), self.y()) } }
启动系统代码
pub(crate) fn init_grids(mut commands: Commands) { debug!("Initializing grids..."); // 初始化u8范围的所有网格 for x in 0..u8::MAX { for y in 0..u8::MAX { commands.spawn(Grid::new(x, y)); } } } pub(crate) fn paint_grids( grid_query: Query<&Grid>, mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>, ) { debug!("Painting grids..."); // 遍历每个网格 for grid in grid_query.iter() { let (grid_x, grid_y) = grid.indices(); // 根据坐标和的奇偶性选择黑白颜色 let color = if (grid_x + grid_y) % 2 == 0 { Color::BLACK } else { Color::WHITE }; // 计算网格像素位置 let pos_x = grid_x * GRID_SIZE; let pos_y = grid_y * GRID_SIZE; // 创建矩形网格 let mesh_handler = Mesh2dHandle(meshes.add(Rectangle::new(GRID_SIZE as f32, GRID_SIZE as f32))); // 绘制矩形 commands.spawn(MaterialMesh2dBundle { mesh: mesh_handler, material: materials.add(color), transform: Transform::from_xyz(pos_x as f32, pos_y as f32, 0.0), ..Default::default() }); } }
其中GRID_SIZE是值为16的u8常量。我已初始化DefaultPlugins和Camera2dBundle,但屏幕仍为空白灰色:

我熟悉Rust但刚接触Bevy,想排查问题所在。
环境:
- Bevy 0.13.2
- Rust 1.76.0
更新:项目插件结构
项目通过CorePlugin管理所有插件,当前仅包含GridPlugin,相关代码如下:
main.rs
use bevy::app::App; use oxidized_pixel_dungeon::core::CorePlugin; fn main() { App::new().add_plugins(CorePlugin).run(); }
core/mod.rs
use bevy::{ app::{Plugin, PluginGroup, Startup}, core_pipeline::core_2d::Camera2dBundle, ecs::system::Commands, log::LogPlugin, utils::tracing::field::debug, DefaultPlugins, }; use crate::grid::GridPlugin; pub struct CorePlugin; impl Plugin for CorePlugin { fn build(&self, app: &mut bevy::prelude::App) { let default_plugins = DefaultPlugins.set(if cfg!(debug_assertions) { LogPlugin { level: bevy::log::Level::TRACE, filter: "info,wgpu_core=warn,wgpu_hal=warn,oxidized_pixel_dungeon=trace".into(), ..Default::default() } } else { LogPlugin { level: bevy::log::Level::INFO, filter: "info,wgpu_core=warn,wgpu_hal=warn".into(), ..Default::default() } }); app.add_plugins(default_plugins) .add_systems(Startup, init_system) .add_plugins(GridPlugin); } } fn init_system(mut commands: Commands) { debug("Running CorePlugin::init_system"); commands.spawn(Camera2dBundle::default()); }
grid/mod.rs
pub mod components; pub(crate) mod constants; mod systems; use bevy::{ app::{Plugin, Startup}, asset::Assets, ecs::system::{Commands, ResMut}, log::debug, math::primitives::Rectangle, render::{color::Color, mesh::Mesh}, sprite::{ColorMaterial, MaterialMesh2dBundle, Mesh2dHandle}, transform::components::Transform, }; use crate::grid::systems::{init_grids, paint_grids}; pub(super) struct GridPlugin; impl Plugin for GridPlugin { fn build(&self, app: &mut bevy::prelude::App) { debug!("Initializing GridPlugin..."); app.add_systems(Startup, (init_grids, paint_grids)); } }
问题原因及解决方案
1. Startup系统执行顺序问题
你将init_grids和paint_grids放在同一Startup系统组中,Bevy的Startup系统默认并行执行,导致paint_grids查询Grid实体时,init_grids可能还未完成实体生成,最终查询不到任何Grid,自然无法渲染网格。
修复方式:
强制两个系统顺序执行,使用chain确保init_grids先完成:
// 修改GridPlugin的build方法 app.add_systems(Startup, init_grids.chain(paint_grids));
2. 网格数量过载(可选优化)
当前生成了u8::MAX × u8::MAX = 65535个网格,会占用大量资源甚至导致渲染异常。建议先测试小范围网格:
// 修改init_grids中的循环 for x in 0..8 { for y in 0..8 { commands.spawn(Grid::new(x, y)); } }
3. 资源复用优化(可选)
当前每个网格都创建独立的Mesh和Material,完全没必要。可复用同一个矩形Mesh和黑白两种Material:
// 修改paint_grids系统 pub(crate) fn paint_grids( grid_query: Query<&Grid>, mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>, ) { debug!("Painting grids..."); // 复用单个Mesh let mesh = meshes.add(Rectangle::new(GRID_SIZE as f32, GRID_SIZE as f32)); let mesh_handler = Mesh2dHandle(mesh); // 预创建黑白材质 let black_mat = materials.add(Color::BLACK); let white_mat = materials.add(Color::WHITE); for grid in grid_query.iter() { let (grid_x, grid_y) = grid.indices(); let material = if (grid_x + grid_y) % 2 == 0 { black_mat.clone() } else { white_mat.clone() }; let pos_x = grid_x * GRID_SIZE; let pos_y = grid_y * GRID_SIZE; commands.spawn(MaterialMesh2dBundle { mesh: mesh_handler.clone(), material, transform: Transform::from_xyz(pos_x as f32, pos_y as f32, 0.0), ..Default::default() }); } }
内容的提问来源于stack exchange,提问作者Eray Erdin
相关产品推荐
相关产品推荐

