3.3-Stable migration issue with AnimControl

Hello Guys,
I migrated my project to 3.3-stable and I’m having issues with AnimControl
For some of the models (not all of them) I’m getting null from:

AnimControl ctl = am.getAnimControl();

First I thought it only happens for GLTF models (downloaded from sketchfab) but I see that some of the GLTF’s are working as expected.
What do you think might be the problem?


What is am ?

Here is the actual code which searches for the AnimControl in 3.2 it always worked:

private AnimControl findAnimationControl(Spatial sp) {

        AnimControl ctl = sp.getControl(AnimControl.class);
        if(ctl!=null) {
            return ctl;

        if(sp instanceof Node) {
            Node nd=(Node)sp;
            for(Spatial spChild:nd.getChildren()) {
                AnimControl ctlChild = findAnimationControl(spChild);
                if(ctlChild!=null) {
                    return ctlChild;

        return null;


Yes, this will not work for Gltf models on JME 3.3.
JME 3.3 comes with new animation system and loading an animated Gltf model will be loaded with new animation system.

In other word instead of “AnimControl.class” you should look for “AnimComposer.class”.


So this is kind of a breaking change…
I’m trying to replace it to AnimComposer but now I need to also stop using AnimChannel.
What is the equivalent for : AnimControl.createChannel?
Is there any documentation I can find about the migration path from 3.2 to 3.3? especially for breaking changes


Note the old animation system is not removed from JME3.3 yet but deprecated. So you can yet use it if you want to stick with the old animation system. In this case, you should first convert your Gltf models into j3o using JME 3.2, then you can load the j3o in JME 3.3 and use animations as you were using before.

For now, the only documentation we have for the new animation system is this:

and some examples here:

I think we are going to have some more examples in JME 3.3.1 release:

1 Like

@adi.barda the 3.3 change updated Animation System. When you export models using 3.2 it generate AnimControl for model, but when you export using 3.3 it will generate AnimComposer control that is new Animation control class. When using 3.3 you should use AnimComposer, im not sure if AnimControl still work in 3.3, but anyway when you export to j3o / load other format then AnimComposer is created instead of AnimControl.

you can see JME Tests for 3.3 for animComposer i belive(Ali provided links for tests). There should also be some documentation.
AnimComposer allow you to blend between animations, you can set what bones animation is assigned too. The Blend is something new, i think there was no blending in AnimControl.

There is also some AnimMigrationclass that can be used on 3.2 exported models for using AnimComposer class purpose. But in your case it looks like you have 3.3 exported models so you already just have AnimComposer class there.

In Any way, like Ali said, you need use AnimComposer since your models seems to also be exported using 3.3 so this class was created and no AnimControl is in scene graph of model.

1 Like

It should work.

Note this only happens with Gltf loader, using an already exported j3o which is exported with old animation system will be also loaded with the old animation system in JME 3.3.

1 Like

yes yes, thats why keyword here is “export” :slight_smile:

when its already exported, then scenegraph have old control ofc like you say.

OK, now it’s working for me. But I cannot find the equivalent for the old AnimEventListener interface. I need to know the status of the current animation, specifically when it ends.
Looking at the samples I can’t see something similar…

To determine when an AnimClip ends, some people append a CallMethod tween. See TestRagdollCharacter for example.

Edit: or this forum post … [SOLVED] When AnimComposer reaches the end of an Action

1 Like

I found that inheriting BaseAction was the easiest for me:

public class CharacterAction extends BaseAction {

        AnimComposer ac;

        public CharacterAction(Tween delegate, AnimComposer ac) {
            this.ac = ac;


        public boolean interpolate(double t) {
            boolean running = super.interpolate(t);
            if (!running) {
            return running;


and then in my controller I did that:

Action ac = control.getAction(animationName);

            if(ac==null) {
                Action originalAction = control.action(animationName);
                ac = new CharacterAction(this,originalAction, control);
                control.addAction(animationName, ac);


            Double animSpeed = Double.parseDouble(speed);

I see that the Action is never really removed. Next time you call: AnimComposer.getAction it returns the prevously used Action even though I removed it from the default layer. Is this by design?

1 Like

will not remove it from AnimComposer, it will just stop it from being played. If you want to permanently remove it use AnimComposer.removeAction()