You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:59:52