Skip to content

SceneComponent not implicitly added when using .spawn() directly on the scene function #24557

Description

@Cpapa97

Bevy version and features

0.19.0-rc.2 and main (as of 16ac0c4)

What you did

Spawned a scene component with an empty bsn! {} using the NewSceneComponent::scene.spawn() api.

What went wrong

Was expecting the SceneComponent to be implicitly added, but it was silently ignored.

While constructing the minimal example, in some cases bevy would send the error

ERROR bevy_scene::scene_component: Entity 370v0 was spawned with the "scene component" bevy_bsn_issues::Player, but without its scene. Scene components should not be spawned directly as components. Instead, they should be spawned as "scenes" using world.spawn_scene or commands.spawn_scene. Scene components should be included using `@bevy_bsn_issues::Player` syntax in BSN.

which clued me in on what was missing. The error first showed up when I was testing on main. However in the current minimal example it doesn't emit any error, even on main.

Additional information

Not sure if this counts as a bug, but it was definitely surprising at first until I understood what was going on.
At least the error not always showing up would be a bug imo, as otherwise it's silently ignored.

(To be clear, this is using the @ syntax that's on main, rather than the : syntax in the rc.2 version.)

Minimal example:

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(
            Startup,
            (
                Player::scene.spawn(), // If this is used, it will not implicitly add the Player component
                // spawn_player.spawn(), // If this is used, it will implicitly add the component
                check_if_scene_component_implicitly_added,
            )
                .chain(),
        )
        .run();
}

#[derive(SceneComponent, Default, Clone)]
struct Player;

impl Player {
    fn scene() -> impl Scene {
        // Player is implicitly added, as long as the @SceneComponent syntax is used in a later bsn call
        // If spawned directly then it is silently not added, though in some situations (not sure which)
        // it gives an error that directs the usage of the @ syntax.
        bsn! {}
    }
}

fn spawn_player() -> impl Scene {
    bsn! {
        @Player
    }
}

fn check_if_scene_component_implicitly_added(query: Option<Single<(), With<Player>>>) {
    match query {
        Some(_) => info!("Player SceneComponent implicitly added"),
        None => info!("Player SceneComponent was NOT implicitly added"),
    }
}

Workaround:

fn spawn_player() -> impl Scene {
    bsn! {
        @Player
    }
}

The workaround is shown in the docs as the intended way to handle this, though I imagine others might try to use the .spawn() convenience on the scene function expecting it to work (and when the error fails to be emitted it might seem to work).

Metadata

Metadata

Assignees

Labels

A-ScenesComposing and serializing ECS objectsC-BugAn unexpected or incorrect behaviorS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions