如何在Bevy中为GLTF场景添加父实体并挂载ComponentFoo?
Hey, let's break down what's going on here and fix your problem step by step.
First, the error you're seeing (Cannot add component because the 'current entity' is not set) happens because commands.spawn_scene() doesn't create a single parent entity for your GLTF scene. Instead, it directly spawns all the entities from the GLTF file into the world—there's no "current entity" to attach your ComponentFoo to when you chain .with(). current_entity().unwrap() also fails for the same reason: there's no active entity being spawned in that chain.
1. Get a Parent Entity for Your GLTF Scene (and Attach ComponentFoo Directly)
The right way to get a controllable parent entity for your entire scene is to use SceneBundle instead of spawn_scene(). This creates a root entity that all GLTF scene entities will be parented to, and you can attach your component directly to this root:
use bevy::prelude::*; // Your custom component #[derive(Component)] struct ComponentFoo; fn load_scene(mut commands: Commands, asset_server: Res<AssetServer>) { // Load the GLTF asset let gltf_handle = asset_server.load("models/FlightHelmet/FlightHelmet.gltf"); // Spawn a root entity with SceneBundle and your component let scene_root_entity = commands.spawn(( SceneBundle { // Extract the Scene handle from the GLTF asset scene: gltf_handle.typed::<Scene>(), transform: Transform::default(), ..Default::default() }, ComponentFoo {}, // Attach your component here! )).id(); // Now you have the root entity stored in scene_root_entity for later use }
This root entity comes with Transform and GlobalTransform out of the box, and every entity from your GLTF scene will be its child. Perfect for what you need.
2. Traverse All Entities in the Scene
If you need to iterate over every entity in the GLTF scene, you have two reliable options:
Option A: Recurse Through the Root Entity's Children
Since all scene entities are children of the root you spawned, you can use a Query<&Children> to walk the hierarchy:
fn traverse_scene( root_entity: Entity, children_query: &Query<&Children>, // Use a closure to handle each entity mut handler: impl FnMut(Entity), ) { // Process the current entity first handler(root_entity); // Recursively process all children if let Ok(children) = children_query.get(root_entity) { for &child in children { traverse_scene(child, children_query, &mut handler); } } } // Example usage in a system: fn process_scene_entities( scene_root_entity: Res<YourSceneRootResource>, // Store the root entity in a resource children_query: Query<&Children>, mut transform_query: Query<&mut Transform>, ) { traverse_scene(scene_root_entity.0, &children_query, |entity| { // Do something with each entity, e.g. print its ID or modify its transform println!("Scene entity ID: {:?}", entity); if let Ok(mut transform) = transform_query.get_mut(entity) { // Adjust transform if needed } }); }
Option B: Filter by SceneInstance Component
If you used spawn_scene() (and don't have a root entity), every entity from the scene will have a SceneInstance component linking it to the original scene handle. You can query for these:
fn get_all_scene_entities( target_scene: Handle<Scene>, query: Query<(Entity, &SceneInstance)>, ) -> Vec<Entity> { query.iter() .filter(|(_, instance)| instance.scene == target_scene) .map(|(entity, _)| entity) .collect() }
3. Locate the GLTF's Root Transform Entity
If you did use spawn_scene() and need to find the top-level transform entity from the GLTF file (not a manually created root), look for an entity with Transform that has no parent (i.e., no Parent component) and belongs to your scene:
fn find_gltf_root_transform( target_scene: Handle<Scene>, query: Query<(Entity, &Transform, &SceneInstance)>, parent_query: Query<&Parent>, ) -> Option<Entity> { query.iter() .filter(|(_, _, instance)| instance.scene == target_scene) // Find entities that don't have a parent .find(|(entity, _, _)| !parent_query.contains(*entity)) .map(|(entity, _, _)| entity) }
But again, using SceneBundle to create your own root entity is better—it gives you explicit control, no need to hunt for the root later.
内容的提问来源于stack exchange,提问作者Simon

