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

在Rapier2D与Bevy中使用filter_groups属性过滤失效问题

使用Bevy Rapier的filter_groups无法过滤障碍物的解决方法

尝试用KinematicCharacterController的filter_groups属性过滤部分障碍物,但始终无效,切换为filter_flags: QueryFilterFlags::all()时功能正常,但业务需求必须用filter_groups实现部分固定障碍物的过滤。当前角色的代码实现如下:

fn setup(
    mut commands: Commands,
    mut atlases: ResMut<Assets<TextureAtlas>>,
    server: Res<AssetServer>,
) {
    let image_handle: Handle<Image> = server.load("spritesheets/spritesheet_Mario.png");
    let texture_atlas = TextureAtlas::from_grid(
        image_handle,
        Vec2::new(SPRITE_MARIO_WIDTH, SPRITE_MARIO_HEIGHT),
        SPRITESHEET_COLS,
        SPRITESHEET_ROWS,
        Option::from(Vec2::new(SPRITE_PADDING_X, SPRITE_PADDING_Y)),
        Option::from(Vec2::new(SPRITE_OFFSET_X, SPRITE_OFFSET_Y)),
    );
    let atlas_handle = atlases.add(texture_atlas);

    commands
        .spawn(SpriteSheetBundle {
            sprite: TextureAtlasSprite::new(SPRITE_IDX_STAND),
            texture_atlas: atlas_handle,
            transform: Transform {
                scale: Vec3::new(
                    SPRITE_RENDER_WIDTH / SPRITE_MARIO_WIDTH,
                    SPRITE_RENDER_HEIGHT / SPRITE_MARIO_HEIGHT,
                    1.0,
                ),
                translation: Vec3::new(WINDOW_LEFT_X + 300.0, WINDOW_BOTTOM_Y + 300.0, 0.0),
                ..Default::default()
            },
            ..Default::default()
        })
        .insert(RigidBody::KinematicPositionBased)
        .insert(Collider::cuboid(
            SPRITE_MARIO_WIDTH / 2.0,
            SPRITE_MARIO_HEIGHT / 2.0,
        ))
        .insert(KinematicCharacterController{
            filter_groups: Option::from(CollisionGroups::new(
            Group::GROUP_1,
            Group::ALL, // Even if I try to filter ALL
            )),
            ..Default::default()
        })
        .insert(Direction::Right)
        .insert(ActiveEvents::COLLISION_EVENTS)
        .insert(ActiveHooks::MODIFY_SOLVER_CONTACTS);
}

问题原因

filter_groups的碰撞规则是双向匹配的:只给角色设置CollisionGroups没用,必须给需要过滤的障碍物也配置对应的CollisionGroups,且两者的组规则要满足:

  • 角色的CollisionGroups第二个参数(允许碰撞的组)需排除目标障碍物的组
  • 障碍物的自身组要被角色的排除规则覆盖

解决方案

  1. 给需要过滤的障碍物实体添加CollisionGroups,将其归为特定组(比如GROUP_2)
  2. 调整角色的filter_groups,排除该组的障碍物
  3. 确保没有其他过滤配置(如filter_flags)干扰filter_groups的生效

修改后的角色代码

.insert(KinematicCharacterController{
    filter_groups: Some(CollisionGroups::new(
        Group::GROUP_1,
        Group::ALL - Group::GROUP_2, // 排除GROUP_2的障碍物
    )),
    ..Default::default()
})

障碍物配置示例

// 不需要被角色碰撞的障碍物
commands.spawn((
    SpriteBundle { /* 障碍物渲染组件 */ },
    RigidBody::Fixed,
    Collider::cuboid(50.0, 50.0),
    CollisionGroups::new(
        Group::GROUP_2, // 自身属于GROUP_2
        Group::ALL, // 可根据需求设置允许碰撞的其他组
    ),
));

// 需要被角色碰撞的障碍物(可使用默认组或GROUP_1)
commands.spawn((
    SpriteBundle { /* 障碍物渲染组件 */ },
    RigidBody::Fixed,
    Collider::cuboid(50.0, 50.0),
    CollisionGroups::new(
        Group::GROUP_1,
        Group::ALL,
    ),
));

补充说明

如果需求是只和特定组碰撞,可直接指定允许的组,比如Group::GROUP_1 | Group::GROUP_3,表示只与GROUP_1、GROUP_3的实体产生碰撞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:25:22