#How to get access to the AnimationPlayer created with gltf scene

12 messages ยท Page 1 of 1 (latest)

heavy fjord
#

I spawn an entity with several my custom components and with a scene bundle, obtained from the gltf:

    let human_gltf = gltf_assets.get(&app_assets.human_gltf).unwrap();
    let human_scene = human_gltf.scenes[0].clone();

    commands.spawn((
        Human::default(),
        Player,
        SceneBundle {
            scene: human_scene,
            ..Default::default()
        },
    ));

And now I want to play animations for entities with "Human" components:

fn update_humans(mut q: Query<(Entity, &Human)>, mut animation_player_q: Query<&AnimationPlayer>) {
    for (entity, human) in q.iter_mut() {
        let animation_player = animation_player_q.get(entity).unwrap();
    }
}

But this fails since the Entity with Human component doesn't have an AnimationPlayer component.
So, I need somehow extract this component from the child scene which is available as a SceneInstance component on the entity.
I can get access to this SceneInstance like so:

fn update_humans(mut q: Query<(Entity, &Human, &SceneInstance)>, mut animation_player_q: Query<&AnimationPlayer>) {
    for (entity, human, scene) in q.iter_mut() {
        let animation_player = animation_player_q.get(entity).unwrap();
    }
}

But I don't quite understand how to extract the AnimationPlayer from it...

Or maybe there must be some other way (without querying the SceneInstance?)

PS: I understand how to handle AnimationPlayers via the asset_server.load("...glb#Animation0"), but my goal is to handle them sort of manually, querying the scene

agile kestrel
#

@heavy fjord just for my understanding, have you checked where in the hierarchy the AnimationPlayer is present?

#

As a side note, this

fn update_humans(mut q: Query<(Entity, &Human)>, mut animation_player_q: Query<&AnimationPlayer>) {
    for (entity, human) in q.iter_mut() {
        let animation_player = animation_player_q.get(entity).unwrap();
    }
}

can be simplified to something like

fn update_humans(mut q: Query<&AnimationPlayer, With<Human>>) {
    for mut animation_player in q.iter_mut() {
        // do something with animation player
    }
}
heavy fjord
#

Yes, but I used explicit animation_player_q because the Human itself doesn't have the AnimationPlayer, that is the main problem ๐Ÿ™‚
So, I decided that I need this animation player query mechanism at some point to request the player as soon as I manage to find the correct entity which stores this player.

just for my understanding, have you checked where in the hierarchy the AnimationPlayer is present?
If I remember correctly, AnimationPlayer is a component of a Scene (this scene is a child of the entity with Human component).

agile kestrel
# heavy fjord Yes, but I used explicit animation_player_q because the Human itself doesn't hav...

Alright so I think what I would do is spawn the scene with something like bevy-scene-hook and create in the Human component create a reference to the entity that has the AnimationPlayer. So:

#[derive(Component)]
struct Human {
    animation_root: Entity,
}

Then query with

fn update_humans(mut q: Query<&Human>, mut animation_player_q: Query<&AnimationPlayer>) {
    for human in q.iter_mut() {
        let animation_player = animation_player_q.get(human.entity).unwrap();
    }
}
heavy fjord
#

bevy is a little bit more convoluted than I thought ๐Ÿ™‚
my brain is melting, but I almost there, thanks for the ideas...

heavy fjord
#

okay, something like this

fn setup_scene(mut commands: Commands, gltf_assets: Res<Assets<Gltf>>, app_assets: Res<AppAssets>) {
    let human_gltf = gltf_assets.get(&app_assets.human_gltf).unwrap();
    let human_scene = human_gltf.scenes[0].clone();
    let animations = Animations(human_gltf.named_animations.clone());

    commands.spawn((
        Human::default(),
        Player,
        animations,
        SceneBundle {
            scene: human_scene,
            ..Default::default()
        },
    ));
    .......................................................................
}

#[derive(Component)]
struct AnimationRoot(Entity);

fn insert_animation_roots(
    mut commands: Commands,
    q: Query<(Entity, &SceneInstance), (Without<AnimationRoot>, With<Animations>)>,
    scene_spawner_res: Res<SceneSpawner>,
    animation_player_q: Query<&AnimationPlayer>,
) {
    for (entity, scene_instance) in q.iter() {
        for scene_entity in scene_spawner_res
            .iter_instance_entities(**scene_instance)
            .filter(|e| animation_player_q.get(*e).is_ok())
        {
            commands.entity(entity).insert(AnimationRoot(scene_entity));
        }
    }
}

fn update_humans(
    q: Query<(&AnimationRoot, &Animations)>,
    mut animation_player_q: Query<&mut AnimationPlayer>,
) {
    for (animation_root, animations) in q.iter() {
        let mut animation_player = animation_player_q.get_mut(animation_root.0).unwrap();
        animation_player.play(animations.0.get("idle").unwrap().clone()).repeat();
    }
}

agile kestrel
#

Haha I know what you mean with it being convoluted sometimes, I do like how it feels like you're in control once you work through something like this. A feeling I find harder to come by with the bigger engines

#

Did it end up working?

#

Also I dunno if you are familiar/interested with open source dealings but if you want you can check the github issues to see if anyone has similar issues with this and then potentially file your own feature request or bug report

heavy fjord
#

Yes, for now it is working.
I skimmed through the issues on github, as well as the help forum here. Not so much information about surgering the gltf manually and obtaining specific handles to a specific parts of the asset.
But anyway, this is my 4th day with bevy and the main problem is just a lack of understanding. And in general all this hassle is sort of exercise to understand the mechanics, that's why I don't want to use any plugins or hooks or whatnot for now.
Before that I was making small games (and some general graphics programming) using bare C and opengl and it was in some sense easier than that ๐Ÿ™‚ Also taking into the account that in general I really don't like Rust. But I want to practice now in something more high level (but not so high level as game engines like unity or godot)...
Well, anyway, will see how it goes, thanks for your answers ๐Ÿ™‚

agile kestrel
#

Happy to help! And good luck on your journey ๐Ÿš€