对于上下文,我正在创建一个简单的游戏引擎。
我的游戏对象都存储在一个矢量中,每一帧每个对象都被迭代和更新。
这样做的问题是,有时候一个对象需要访问向量中其他对象的数据,我不能传入一个不可变/可变的引用到向量本身,因为它是可变地迭代的。
如何允许每个游戏对象访问同一Vector中其他游戏对象的字段(位置、旋转等)?
以下是导致问题的循环:
for entity in self.scene.collidable_entitys {
match &mut entity.value {
Some(e) => {
e.update(&frame_descriptor, &self.input, &self.scene.collidable_entitys);
entity_count += 1;
}
None => {}
}
}
编译器不喜欢我给self.scene.collidable_entyys一个不可变的引用,因为它被借用来进行迭代。
下面是一个简单例子来说明我的问题。
use std::vec::Vec;
struct Object {
a: u32,
b: u32,
}
impl Object {
fn new() -> Self {
Self {
a: 0,
b: 0,
}
}
fn update(&mut self, objects: &Vec<Option<Object>>) {
// mutate self here
// but also read from the object vector
}
}
fn main() {
println!("Hello, world!");
let mut vector: Vec<Option<Object>> = Vec::new();
vector.push(Some(Object::new()));
vector.push(Some(Object::new()));
vector.push(Some(Object::new()));
for obj in vector.as_ref() {
match obj {
Some(o) => o.update(&vector),
None => {}
}
}
}
任何帮助或我可以使用的系统的替代方案都非常感谢。
2条答案
按热度按时间cdmah0mi1#
entity
是可变借用的,然后你试图借用实体的整个集合。这是不允许的,因为实体现在被借用了两次。通常--特别是在游戏引擎中--这个问题可以通过使用实体-组件-系统(ECS)模式来解决。它通过处理实体的句柄而不是引用来解决这个问题。ECS通常非常快,感觉非常适合Rust,因为它完全消除了复杂的借用交互。ECS crates here有一个很大的列表。
如果你不想使用ECS,你仍然可以使用句柄或id代替引用,例如,使用向量索引作为临时id,在很短的范围内借用,以提取出你需要的单个字段。
pn9klfpd2#
一种解决方案是将向量分割为切片:
另一个解决方案是通过
RefCell
利用内部可变性。