Hello animation null pointer exception may have been solved at last

Null pointer exception on: control.addListener(this);

private AnimChannel channel;
  private AnimControl control;
public class Main extends SimpleApplication  implements ActionListener, AnimEventListener{

playerModel = assetManager.loadModel("/Models/character.glb");
    sceneModel.setLocalScale(0.2f);
    
    playerModel.move(0, 0, 7f);
    
    
    /**
     * ANIMATION
     */
   
  
    control = playerModel.getControl(AnimControl.class);
    control.addListener(this);
    channel = control.createChannel();
    channel.setAnim("stand");

  private void setUpKeys() {

    inputManager.addListener(actionListener, "UP");
}

     
  public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
    if (animName.equals("Walk")) {
      channel.setAnim("stand", 0.50f);
      channel.setLoopMode(LoopMode.DontLoop);
      channel.setSpeed(1f);
    }
  }

  public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
    // unused
  }
private ActionListener actionListener = new ActionListener() {
    public void onAction(String name, boolean keyPressed, float tpf) {
      if (name.equals("Walk") && !keyPressed) {
        if (!channel.getAnimationName().equals("Walk")) {
          channel.setAnim("Walk", 0.50f);
          channel.setLoopMode(LoopMode.Loop);
        }
      }
    }
  };

error null pointer exception
control = playerModel.getControl(AnimControl.class);
control.addListener(new PlayerListener());

package mygame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;

/**
 *
 * @author Иван
 */
public class PlayerListener implements AnimEventListener {

    public PlayerListener() {
    }

    @Override
    public void onAnimCycleDone(AnimControl ac, AnimChannel ac1, String string) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onAnimChange(AnimControl ac, AnimChannel ac1, String string) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    
}

AnimControl is deprecated…

how i make animation work?

Try this not work:

/**
 * Get childs
 * 

    
        ArrayList<Spatial> nodes = new ArrayList(playerModel.getChildren());
 
        for(Spatial item:nodes){ 

            Node rootScene= (Node) item;              
           ArrayList<Spatial> nodesChild = new ArrayList(rootScene.getChildren());
           for(Spatial itemChild:nodesChild){
                 System.out.println(itemChild.getName());
             }

        }
  */

    /**
     * ANIMATION
     */

  
    
    control = playerModel.getChild("test.001").getControl(AnimControl.class);
    control.addListener(new PlayerListener());
    channel = control.createChannel();
    channel.setAnim("stand");

Try this
rootNode.attachChild(playerModel);

    control = playerModel.getControl(AnimControl.class);
    control.addListener(new PlayerListener());
    channel = control.createChannel();
    channel.setAnim("stand");

null

My controll is null

control = playerModel.getControl(AnimControl.class);

if(control == null){
    System.out.println("null");
}

Method:
control = playerModel.getControl(AnimControl.class);

getControll (Class)
returns null

AnimControl.class is deprecated?

how i can make it work?

 playerModel = (Node)assetManager.loadModel("/Models/character.glb");
    sceneModel.setLocalScale(0.2f);
    rootNode.attachChild(playerModel);
    control = playerModel.getControl(AnimControl.class);

.getControl(AnimControl.class);
returns null
how i can make it works?

You get the control from the spatial that has the control. The one you are trying to get it from does not have it.

https://jmonkeyengine.gitbooks.io/wiki-jmonkeyengine/advanced/traverse_scenegraph.html

can you tell from what you need to get control

or write code example

ogre exporter:
test.001.mesh.xml
try to get control from test.001

  playerModel = (Node)assetManager.loadModel("/Models/character.glb");
    sceneModel.setLocalScale(0.2f);
    rootNode.attachChild(playerModel);
    control = playerModel.getChild("test.001").getControl(AnimControl.class);
    
    playerModel.move(0, 0, 7f);

null

Now we see this question from time to time.

Yes, JME 3.3 uses a new animation system.
When you load an animated gltf/glb/ogre model with JME 3.3 it automatically loads them with the new animation system. You should look for AnimComposer instead of AnimControl.

You can find a bunch of examples here

You can find more examples if you search for AnimComposer in the JME GitHub page and this forum.

Edit:

See these as well:

can you write example for wiki with new animation api?
new hello animation

Actually we do have one done by nehon (he was the author of new animation system) but we have never put it on wiki I guess!

You are welcome to add it to the wiki and submit a PR if you want :slightly_smiling_face:

bug report
please make it vorks.

It’s not a bug. It’s a language barrier. You’re doing it wrong. You need to access the control from the spatial that holds the control.

You can not call .getControl from anywhere and expect it to find it. There may be many controls of the same type. You need to get it from the spatial that has the control.

This is about as good as it gets without someone coding it for you.

Edit: I will add that adding a breaking change right after deprecation is crap though.

from root node?
from level and character control?
forom level node?

package mygame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import mygame.PlayerListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.SceneGraphVisitor;
import com.jme3.scene.Spatial;
import java.util.ArrayList;
/**
 * This is the Main Class of your Game. You should only do initialization here.
 * Move your Logic into AppStates or Controls
 * @author normenhansen
 */



public class Main extends SimpleApplication  implements ActionListener, AnimEventListener {
  private Spatial sceneModel;
  private Node playerModel;
  private float rotationYOld;
  
  private BulletAppState bulletAppState;
  private RigidBodyControl landscape;
  private CharacterControl player;
  private Vector3f walkDirection = new Vector3f();
  private boolean left = false, right = false, up = false, down = false;
AnimChannel channel_walk;

  
  
  //Temporary vectors used on each frame.
  //They here to avoid instanciating new vectors on each frame
  private Vector3f camDir = new Vector3f();
  private Vector3f camLeft = new Vector3f();
  

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    public void simpleInitApp() {
    /** Set up Physics */
    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    //bulletAppState.setDebugEnabled(true);

    // We re-use the flyby camera for rotation, while positioning is handled by physics
    viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
    flyCam.setMoveSpeed(100);
    setUpKeys();
    setUpLight();

    // We load the scene from the zip file and adjust its size.
    //assetManager.registerLocator("new-scene.zip", ZipLocator.class);
    sceneModel = assetManager.loadModel("/Models/untitled.glb");
    sceneModel.setLocalScale(2f);
    
    playerModel = (Node)assetManager.loadModel("/Models/character.glb");
    sceneModel.setLocalScale(0.2f);
    rootNode.attachChild(playerModel);
    
    playerModel.move(0, 0, 7f);
    

  //playerControl.addListener( this);
  /**
     * ANIMATION
     */


    
  

    //playerModel = assetManager.loadModel("Models/character.glb");
    
    // We set up collision detection for the scene by creating a
    // compound collision shape and a static RigidBodyControl with mass zero.
    CollisionShape sceneShape =
            CollisionShapeFactory.createMeshShape(sceneModel);
    landscape = new RigidBodyControl(sceneShape, 0);
    sceneModel.addControl(landscape);
    
    /**
     * We set up collision detection for the player by creating
     * a capsule collision shape and a CharacterControl.
     * The CharacterControl offers extra settings for
     * size, stepheight, jumping, falling, and gravity.
     * We also put the player in its starting position.
     */
    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 3f, 1);
    player = new CharacterControl(capsuleShape, 0.05f);
    player.setJumpSpeed(50);
    player.setFallSpeed(50);

    
    // We attach the scene and the player to the rootnode and the physics space,
    // to make them appear in the game world.
    rootNode.attachChild(sceneModel);

    
    player.setSpatial(playerModel);

    bulletAppState.getPhysicsSpace().add(landscape);
    bulletAppState.getPhysicsSpace().add(player);

    // You can change the gravity of individual physics objects before or after
    //they are added to the PhysicsSpace, but it must be set before MOVING the
    //physics location.
    player.setGravity(new Vector3f(0,-30f,0));
    player.setPhysicsLocation(new Vector3f(4, 12, 4));
    
    
  }
    
        private void setUpLight() {
       // We add light so we see the scene
       AmbientLight al = new AmbientLight();
       al.setColor(ColorRGBA.White.mult(0.5f));
       rootNode.addLight(al);

       DirectionalLight dl = new DirectionalLight();
       dl.setColor(ColorRGBA.White);
       dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
       rootNode.addLight(dl);
  }
     
     private void setUpKeys() {
    inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
    
    
    
    
    inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addListener(this, "Left");
    inputManager.addListener(this, "Right");
    inputManager.addListener(this, "Up");
    inputManager.addListener(this, "Down");
    inputManager.addListener(this, "Jump");
  }
     
  
  
  
  
       /** These are our custom actions triggered by key presses.
   * We do not walk yet, we just keep track of the direction the user pressed. */
  public void onAction(String binding, boolean isPressed, float tpf) {
    if (binding.equals("Left")) {
      left = isPressed;
    } else if (binding.equals("Right")) {
      right= isPressed;
    } else if (binding.equals("Up")) {
      up = isPressed;
    } else if (binding.equals("Down")) {
      down = isPressed;
    } else if (binding.equals("Jump")) {
      if (isPressed) { player.jump(new Vector3f(0,20f,0));}
    }
  }

    @Override
    public void simpleUpdate(float tpf) {
        camDir.set(cam.getDirection()).multLocal(0.6f);
        camLeft.set(cam.getLeft()).multLocal(0.4f);
        walkDirection.set(0, 0, 0);
        if (left) {
            walkDirection.addLocal(camLeft);
        }
        if (right) {
            walkDirection.addLocal(camLeft.negate());
        }
        if (up) {
            walkDirection.addLocal(camDir);
        }
        if (down) {
            walkDirection.addLocal(camDir.negate());
        }
        player.setWalkDirection(walkDirection);
        cam.setLocation(player.getPhysicsLocation());
        
        //Quaternion  playerRotation =  new Quaternion(walkDirection.x,walkDirection.y,walkDirection.z,0);
        //playerModel.setLocalRotation(playerRotation);
       
       //player.setPhysicsLocation(player.getPhysicsLocation());
        playerModel.setLocalTranslation (player.getPhysicsLocation().x , player.getPhysicsLocation().y, player.getPhysicsLocation().z);
        
        
        /**
         * Rotation camera with chacarter
         */
        float[] angles = new float[3];
        cam.getRotation().toAngles(angles); // we get the cam angles here
        angles[0] = 0; // you don't want to rotate along the x-axis, so we set it to 0
        angles[2] = 0; // you don't want to rotate along the z-axis, so we set it to 0
        playerModel.setLocalRotation(playerModel.getLocalRotation().fromAngles(angles));

        //playerModel.setLocalRotation(q);
    }

    @Override
    public void onAnimCycleDone(AnimControl ac, AnimChannel ac1, String string) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void onAnimChange(AnimControl ac, AnimChannel ac1, String string) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }




    
    
    
}