区分移除与消失
我有一个简单的Bevy 0.18观察者,它应该在对应的公开组件被移除时移除一个内部使用的组件:
fn on_remove_animated(event: On<Remove, Animated>, mut commands: Commands) {
commands.entity(event.entity).remove::<TimedBy>();
}
但该观察者在整个实体被撤销时也会触发,在这种情况下,延迟删除命令会发出一个警告:
WARN bevy_ecs::error::handler: Encountered an error in command `<bevy_ecs::system::commands::entity_command::remove<engine::animation::TimedBy>::{{closure}} as bevy_ecs::error::command_handling::CommandWithEntity<core::result::Result<(), bevy_ecs::world::error::EntityMutableFetchError>>>::with_entity::{{closure}}`: Entity despawned: The entity with ID 677v0 is invalid; its index now has generation 1.
Note that interacting with a despawned entity is the most common cause of this error but there are others
If you were attempting to apply a command to this entity,
and want to handle this error gracefully, consider using `EntityCommands::queue_handled` or `queue_silenced`.
是否有办法区分是在仅删除了 Animated 组件,还是整个实体被撤销?如果不能,是否有其他方法,在移除 Animated 组件时安全地移除 TimedBy 组件?
或者我是否必须使用 queue_silenced() 来省略警告?如果这样做,在将尝试在已被撤销的实体上移除组件的命令排队时,是否会有副作用?
解决方案
根据 Remove 的文档,观察者是在组件仍然存在时触发的,这也意味着相关的实体也存在,因此我们无法查询实体是否正在被移除。
当一个组件从实体上被移除时触发,并在组件被移除前执行,因此你仍然可以访问组件数据
但还有另一种方式!通过快速浏览 撤销实体并调用观察者的代码,我发现Bevy会传递关于新实体原型的信息:
deferred_world.trigger_raw(
REMOVE,
&mut Remove {
entity: self.entity,
},
&mut EntityComponentsTrigger {
components: archetype.components(),
old_archetype: Some(archetype),
new_archetype: None,
},
caller,
);
如果一个实体被完全撤销,它会传递 None。
在观察者中检查实体是否正在被撤销
注:本答案自Bevy 0.19版本起才实际可用。
是否有办法区分是仅仅移除了
Animated组件,还是整个实体被撤销?
要检查实体是否正在被撤销,我们可以查看它的新原型——可以通过 on_despawn.trigger().new_archetype 访问。
fn on_remove_animated(event: On<Remove, Animated>, mut commands: Commands) {
if event.trigger().new_archetype.is_some() {
commands.entity(event.entity).remove::<TimedBy>();
}
}
简单地消除警告
注:此代码在Bevy的早期版本也同样适用。
还是需要使用
queue_silenced()来省略警告?
你可以使用那个,或者更简单的方式是使用 try_remove:
fn on_remove_animated(event: On<Remove, Animated>, mut commands: Commands) {
commands.entity(event.entity).try_remove::<TimedBy>();
}
我会说,在像删除相关组件这样的简单场景下,不必犹豫去抑制警告。在你的用例中,这种方法与前一种一样有效,因为正是引入 try_remove 的原因。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。