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

Bevy 0.11小球生成偏移屏幕及边界限制问题求助

问题原因分析

Bevy 0.11 对2D相机的默认坐标系做了重大调整,你参考的旧教程使用的是旧版本Bevy的坐标系逻辑,两者不匹配导致了小球位置异常:

  • 旧版本Bevy:2D相机默认以屏幕左上角为原点(0,0),X轴向右、Y轴向下延伸,屏幕右下角对应坐标为(window.width, window.height)
  • Bevy 0.11+:2D相机默认以屏幕中心为原点(0,0),X轴向右、Y轴向上延伸,屏幕左上角对应(-window.width/2, window.height/2),右下角对应(window.width/2, -window.height/2)

你的代码里把相机和玩家都设置到(window.width/2, window.height/2),在新坐标系下这个点位于屏幕右下角外侧,自然看不到小球;而使用默认Transform时,相机和玩家都在(0,0)(屏幕中心),你看到的(32,32)应该是精灵左上角相对于屏幕的坐标(精灵大小64x64,中心在(0,0)时左上角为(-32,32),可能是坐标显示混淆),此时边界限制代码只适配了向左/向下的移动,是因为旧教程的逻辑基于左上角原点,和新坐标系不兼容。

解决方案

有两种方式可以解决这个问题,根据你的需求选择:

方案1:切换回旧教程的左上角坐标系

修改相机的配置,让它使用旧版本的原点规则,这样你可以完全沿用教程的后续代码:

pub fn spawn_camera(mut commands: Commands, window_query: Query<&Window, With<PrimaryWindow>>) {
    commands.spawn(Camera2dBundle {
        camera_2d: Camera2d {
            // 设置相机原点为屏幕左上角
            default_position: Camera2dDefaultPosition::TopLeft,
            ..default()
        },
        // 相机位置保持在(0,0)即可
        transform: Transform::from_xyz(0.0, 0.0, 0.0),
        ..default()
    });
}

此时你的spawn_player函数无需修改,小球会正确生成在屏幕中心,后续教程的边界限制代码也能直接使用。

方案2:适配Bevy 0.11的中心坐标系

如果你想使用新版本的默认坐标系,需要调整玩家生成位置和边界限制逻辑:

  1. 修改玩家生成位置为屏幕中心(0,0):
pub fn spawn_player(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
) {
    commands.spawn((
        SpriteBundle {
            transform: Transform::from_xyz(0.0, 0.0, 0.0),
            texture: asset_server.load("sprites/ball_blue_large.png"),
            ..default()
        },
        Player {},
    ));
}
  1. 重写边界限制系统,适配中心坐标系:
pub fn constrain_player_movement(
    mut player_query: Query<&mut Transform, With<Player>>,
    window_query: Query<&Window, With<PrimaryWindow>>,
) {
    let window = window_query.get_single().unwrap();
    let mut player_transform = player_query.single_mut();
    let half_player_size = PLAYER_SIZE / 2.0;
    let half_window_width = window.width() / 2.0;
    let half_window_height = window.height() / 2.0;

    // 限制X轴范围:从屏幕左边缘+玩家半径 到 屏幕右边缘-玩家半径
    player_transform.translation.x = player_transform.translation.x.clamp(
        -half_window_width + half_player_size,
        half_window_width - half_player_size,
    );
    // 限制Y轴范围:从屏幕下边缘+玩家半径 到 屏幕上边缘-玩家半径
    player_transform.translation.y = player_transform.translation.y.clamp(
        -half_window_height + half_player_size,
        half_window_height - half_player_size,
    );
}

记得在main函数里添加这个系统:

.add_systems(Update, constrain_player_movement)

内容的提问来源于stack exchange,提问作者robi503

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:32:53