Bevy ECS 有没有办法进行复杂的查询?

nir*_*har 3 rust bevy

是否可以创建直接按组件中字段的值进行过滤的复杂查询?

例如,假设 - 我有一个 2D 棋盘游戏(比如国际象棋或其他游戏),我想弄清楚特定坐标上是否有一个棋子。我的组件如下所示:

#[derive(Component)]
struct BoardPosition {
    x: usize,
    y: usize,
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找位置(4,5)的那块。然后,我的查询将如下所示 - 迭代整个板:

fn some_system(pieces: Query<&BoardPosition>) {
    for piece in pieces.iter() {
        if piece.x == 4 && piece.y == 5 {
            // This is my piece, now I can do whatever I want with it
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

但显然,找到一个简单的片段需要 O(n) 的时间。如果我将板存储为双列表(即[[T; N]; N]),那么通过简单地执行 来找到这块将需要 O(1) board[4][5],但由于 bevy 拥有组件,所以我不能简单地访问该实体(或其其他组件)以此类推。

是否有更智能的方法来执行此操作,这将允许快速查询允许我获取(或更改)所查询实体的其他组件?

kmd*_*eko 6

您可以拥有一个带有数组的“板”以进行快速查找,同时仍然让 Bevy 自己管理这些部分。只需创建一个Board资源(或具有组件的实体Board)来保留对其他实体的引用。然后你可以使用.get()碎片Query来获得碎片。

它应该看起来像这样:

struct Board {
    tiles: [[Option<Entity>; 8]; 8],
}

#[derive(Component)]
struct Piece {
    // they can still have x, y if you want
}

fn some_system(board: Res<Board>, pieces: Query<&Piece>) {
    let entity = board.tiles[4][5].expect("no entity at (4, 5)");
    let piece = pieces.get(entity).expect("entity at (4, 5) is not a Piece");
    // do whatever you want with the piece
}
Run Code Online (Sandbox Code Playgroud)