我正在尝试实现一个使用通用组件的系统,但是当我尝试改变变量时,我一直遇到连接方法的问题。这是我的代码的简化版本:
use specs::{Component, prelude::*};
#[derive(Component, Debug, Default)]
#[storage(NullStorage)]
pub struct FooMarker;
#[derive(Component, Debug, Default)]
#[storage(VecStorage)]
pub struct Foo(pub f64);
pub trait Variable: Component + std::fmt::Debug + Default + Send + Sync + 'static {
fn get_value(&self) -> f64;
fn set_value(&mut self, value: f64);
}
impl Variable for Foo {
fn get_value(&self) -> f64 {
self.0
}
fn set_value(&mut self, value: f64) {
self.0 = value;
}
}
#[derive(Default)]
pub struct ChangeVariableSystem<T: Default=Foo> {
_phantom_variable: std::marker::PhantomData<T>,
}
impl <'a, T> System<'a> for ChangeVariableSystem<T>
where
T: Component + Variable + Default + Send + Sync + 'static,
{
type SystemData = (
ReadStorage<'a, FooMarker>,
WriteStorage<'a, T>,
);
fn run(&mut self, data: Self::SystemData) {
let (
markers,
mut variables,
) = data;
(&variables, &markers).join()
.for_each(|(variable, _)| {
variable.get_value();
println!("{:?}", variable);
});
(&mut variables, &markers).join()
.for_each(|(variable, _)| {
variable.set_value(1.0);
println!("{:?}", variable);
});
}
}
fn main() {
let mut world = World::new();
world.register::<Foo>();
world.register::<FooMarker>();
for _ in 0..10 {
world.create_entity()
.with(Foo(0.0))
.with(FooMarker)
.build();
}
let mut dispatcher = DispatcherBuilder::new()
.with(
ChangeVariableSystem::<Foo>::default(),
"change_variable_system",
&[],
).build();
}
在前面的代码中,我在第一个连接中没有出现问题,因为变量没有发生变化,但在第二个连接中,我遇到了以下问题:
error[E0599]: the method `join` exists for tuple `(&mut Storage<'_, T, FetchMut<'_, MaskedStorage<T>>>, &Storage<'_, FooMarker, Fetch<'_,
MaskedStorage<FooMarker>>>)`, but its trait bounds were not satisfied
--> project\examples\generics.rs:60:36
|
60 | (&mut variables, &markers).join()
| ^^^^ method cannot be called due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`&mut Storage<'_, T, FetchMut<'_, MaskedStorage<T>>>: specs::Join`
which is required by `(&mut Storage<'_, T, FetchMut<'_, MaskedStorage<T>>>, &Storage<'_, FooMarker, Fetch<'_, MaskedStorage<FooMarker>>>): specs::Join`
`<T as specs::Component>::Storage: SharedGetMutStorage<T>`
which is required by `(&mut Storage<'_, T, FetchMut<'_, MaskedStorage<T>>>, &Storage<'_, FooMarker, Fetch<'_, MaskedStorage<FooMarker>>>): specs::Join`
For more information about this error, try `rustc --explain E0599`.
我不知道如何解决这个问题。组件特征绑定不应该足以解决问题吗?你能帮助我吗?
我刚刚使用规范版本 0.19 尝试了同样的操作,并且成功了。这是0.20版本的bug吗?
谢谢!
v0.20.0 确实改变了这一点(添加了特征界限)。您现在需要添加
where T::Storage: SharedGetMutStorage<T>
边界。let variable = variable.access_mut();
您还需要在第二个闭包的开头添加,以访问该值。