Rust(Bevy):ECS网络数据结构

4

我不确定我是否完全理解实体组件系统方法,这可能是出现这个问题的原因之一。仍在努力摆脱面向对象编程思维!

我正在尝试创建类似于网络的数据结构,例如电路:

Circuit.

因此,例如,实体4连接到1,1连接到2,依此类推。到目前为止,我已经理解了如何创建组件,但我无法理解应该如何存储连接信息。我相信实体应该指向另一个实体?!?我还想象过最好的做法是有一个将具有连通性信息的组件,但在这种情况下,它应该存储什么?理想情况下应该是实体本身,对吗?怎么做呢?

1个回答

3

在处理Bevy中的实体时,应该始终使用它们的ID来引用其他实体,不要在系统运行之间存储指向这些实体的指针。

Bevy中的实体ID存储在结构体Entity中。注意:

实体的轻量级唯一标识符。

此外,如果此网络对于您的游戏是独特的(例如,在整个游戏中最多只有一个实例),则可以将其连通性数据存储在"资源"中。当您创建和处理大量实体和组件时,可以获得ECS的最大好处。

我无法就您特定的用例发表更多意见,因为我不知道会有多少个网络,您计划如何使用它们以及与它们交互的方式。ECS是DDD模式(数据驱动开发),因此架构取决于存在多少数据,这些数据具有哪些属性以及如何使用它们。

多个网络的示例

如果您有多个网络,可以以以下方式存储它们:

#[derive(Component)]
struct NetworkTag; // Any entity with this tag is network.

// Spawn network into world like this
let network_id: Entity = world.spawn()
     .insert(NetworkTag)
     .id();

你可以以这种方式存储电网的部分:

#[derive(Component)]
struct PlusConnections(Vec<Entity>);

#[derive(Component)]
struct NetworkId(Entity);

// Spawn part into world like this
let part_id = world.spawn()
       .insert(NetworkId(network_id))
       .insert(PlusConnections(other_part_ids));

完成这样生成部件后,您只会知道正极的连接,但是您可以在单独的系统中填充负极。例如:
#[derive(Component)]
struct NegConnections(Vec<Entity>);

fn fill_negatives_system(
   query_el_parts: Query<(Entity, &PlusConnections)>,
   query_el_parts_wo_neg: Query<Entity, Without<NegConnections>>,
   mut commands: Commands
){
   let mut positive_to_negative: HashMap<Entity, Vec<Entity>> = HashMap::new();
   for (neg, pc) in query_el_parts.iter(){
       for &positivein pc.0.iter(){
          positive_to_negative.entry(positive).or_default().push(neg);
       }
   }
   for (pos, negatives) in positive_to_negative{
      commands.entity(pos).insert(NegConnections(negatives));
   }
   // At the next tick, all nodes in electric grid would know what is their negative and positive connections and in which networks they are stored.
}


虽然我也不知道OP的具体用例,但是从这个图中我可以理解到以下内容(并且自己在应用程序中也可以使用)。假设你有四个电力组件(实体)-开关,电池,电阻和LED。每一个都连接着两个或更多其他组件,并且方向很重要。因此,我可能希望查询“与这个LED相连的是什么”,并得到回答说,它的正极连接了一个电池,负极连接了一个电阻。我不是很清楚资源如何帮助我们做到这一点 - 它们难道不是世界/全局对象吗? - John C
如果我将这些网络组件存储为具有组件的实体,并且我只有一个网络,那么我可以以这种方式存储它们的链接:struct Network { negatives: HashMap<Entity, Vec<Entity>>, positive_conns: HashMap<Entity, Vec<Entity>> }。因此,如果我有LED的ID,我们可以查找它有哪些连接,然后从查询中查询其他组件。如果我有多个网络,我可以将这些连接存储在单独的组件中(例如struct PositiveConnections(Vec<Entity>)),并将它们附加到网络的每个部分。 - Angelicos Phosphoros
嗯,我不太了解ECS是否能够正常工作,而且似乎OP也不会让我明白,但是看起来很不错,所以给你发了个赏金。 :) - John C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接