AI does not recognize hill

Hello,
I just want to add a simple AI that moves to a certain point and avoids the obstacles in the way. The only obstacles are so far hills in the terrain (made in the SDK). This is the code:
[java]package mygame;

import com.jme3.ai.navmesh.NavMesh;
import com.jme3.ai.navmesh.NavMeshPathfinder;
import com.jme3.ai.navmesh.Path.Waypoint;
import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    private BulletAppState bulletAppState;
    private Spatial enemy;
    private BetterCharacterControl enemyControl;
    private NavMeshPathfinder navi;

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

    @Override
    public void simpleInitApp() {
    flyCam.setMoveSpeed(100f);
    cam.setLocation(new Vector3f(0f,50f,0f));
    bulletAppState = new BulletAppState();

     stateManager.attach(bulletAppState);
     bulletAppState.setDebugEnabled(true);
     initTerrain();
     initLight();
     initEnemy();
    

    }

    private void initTerrain() {
    Spatial terrain = assetManager.loadModel(“Scenes/Scene.j3o”);
    RigidBodyControl terrainControl = new RigidBodyControl(0f);
    terrain.addControl(terrainControl);
    bulletAppState.getPhysicsSpace().add(terrainControl);
    rootNode.attachChild(terrain);
    Node n = (Node) terrain;
    Geometry geom = (Geometry) n.getChild(“NavMesh”);
    Mesh mesh = geom.getMesh();
    System.out.println(geom.getName());
    NavMesh navMesh = new NavMesh(mesh);
    navi = new NavMeshPathfinder(navMesh);
    }

    private void initLight() {
    /**
    * A white, directional light source
    */
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection((new Vector3f(-0.5f, -2f, -0.5f)).normalizeLocal());
    sun.setColor(ColorRGBA.White);
    rootNode.addLight(sun);
    }

    private void initEnemy() {
    enemy = assetManager.loadModel(“Models/skeleton.j3o”);
    enemyControl = new BetterCharacterControl(0.5f, 4f, 70f);
    enemy.addControl(enemyControl);
    bulletAppState.getPhysicsSpace().add(enemyControl);
    enemyControl.warp(new Vector3f(0f, 0f, -80f));
    //enemyControl.setGravity(new Vector3f(0f, -30f, 0f));
    rootNode.attachChild(enemy);
    navi.setPosition(enemy.getLocalTranslation());

    /* Spatial obstacle = assetManager.loadModel("Models/skeleton.j3o");
     BetterCharacterControl obstacleControl = new BetterCharacterControl(1f,4f,50f);
     obstacle.addControl(obstacleControl);
     bulletAppState.getPhysicsSpace().add(obstacleControl);
     obstacleControl.warp(new Vector3f(0f, 3f, 20f));
     obstacleControl.setGravity(new Vector3f(0f, -50f, 0f));
     rootNode.attachChild(obstacle);*/
     
     navi.computePath(new Vector3f(0f, 0f, 0f));
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    Waypoint wayPoint = navi.getNextWaypoint();
    if (wayPoint == null) {
    return;
    }
    Vector3f vector = wayPoint.getPosition().subtract(enemy.getLocalTranslation());
    if (!(vector.length() < 1)) {
    enemyControl.setWalkDirection(vector.normalizeLocal().multLocal(tpf * 500));
    } else {
    navi.goToNextWaypoint();
    }
    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }
    [/java]

The problem is, that the enemy is moving towards the point with ignoring any hills and because a hill is in the way, it moves against it and gets stuck.It does not even try to get around it…

Any ideas?

Look at your navmesh when you create it (select it in the SceneExplorer) and adjust the values when you create it.

I’ve tried really many values now, the character is just walking towards the wall… But I noticed that there was somehow no mesh at my wall. Maybe this is a problem? Here is an image:

I tried to fix this but I didn’t manage it…

The hills on the right are marked as an area that the character can walk on. Probably because it doesn’t reach the maximum slope you enter in the settings.

Yeah sorry I forgot to add: The character is at the left side of the hills (left of the high hill) and I calculate the path to go between them. He walks in a straight line to the target position and gets of course blocked by the hill.

Well your loop drains the whole waypoint queue in a few frames… The character will go in the direction of waypoint 1 for one frame, then 2 for one frame etc. and then to the last waypoint for the rest of the time until it arrives.

1 Like

Thanks Normen! That was the problem. Another one was, that the position of the Spatial enemy was not the same as the Vector where I warped the BetterCharacterControl (after 1 frame or so the position got synchronized). So here is the Code that works for me:

[java]package mygame;

import com.jme3.ai.navmesh.NavMesh;
import com.jme3.ai.navmesh.NavMeshPathfinder;
import com.jme3.ai.navmesh.Path.Waypoint;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    private BulletAppState bulletAppState;
    private Spatial enemy;
    private BetterCharacterControl enemyControl;
    private NavMeshPathfinder navi;

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

    @Override
    public void simpleInitApp() {
    flyCam.setMoveSpeed(100f);
    cam.setLocation(new Vector3f(0f, 50f, 0f));
    bulletAppState = new BulletAppState();

     stateManager.attach(bulletAppState);
     bulletAppState.setDebugEnabled(true);
     initTerrain();
     initLight();
     initEnemy();
    

    }

    private void initTerrain() {
    Spatial terrain = assetManager.loadModel(“Scenes/Scene.j3o”);
    RigidBodyControl terrainControl = new RigidBodyControl(0f);
    terrain.addControl(terrainControl);
    bulletAppState.getPhysicsSpace().add(terrainControl);
    rootNode.attachChild(terrain);
    Node n = (Node) terrain;
    Geometry geom = (Geometry) n.getChild(“NavMesh”);
    Mesh mesh = geom.getMesh();
    NavMesh navMesh = new NavMesh(mesh);
    navi = new NavMeshPathfinder(navMesh);
    }

    private void initLight() {
    /**
    * A white, directional light source
    */
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection((new Vector3f(-0.5f, -2f, -0.5f)).normalizeLocal());
    sun.setColor(ColorRGBA.White);
    rootNode.addLight(sun);
    }

    private void initEnemy() {
    enemy = assetManager.loadModel(“Models/skeleton.j3o”);
    enemyControl = new BetterCharacterControl(1f, 4f, 70f);
    enemy.addControl(enemyControl);
    bulletAppState.getPhysicsSpace().add(enemyControl);
    enemyControl.warp(new Vector3f(0f, 0f, -80f));
    enemyControl.setGravity(new Vector3f(0f, -30f, 0f));
    rootNode.attachChild(enemy);
    navi.setPosition(new Vector3f(0f, 0f, -80f)); //Here the position of the Spatial is not the same as the position I warped the Control to

      new Thread(new Runnable() {
          @Override
          public void run() {
              navi.computePath(new Vector3f(0f, 0f, 0));
          }
      }).start();
     //showWaypoints();
    

    }

    private void showWaypoints() {
    Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
    mat.setColor(“Color”, ColorRGBA.Red);

     for (Waypoint w : navi.getPath().getWaypoints()) {
         Box b = new Box(1, 1, 1);
         Geometry geom = new Geometry("Box", b);
    
         geom.setMaterial(mat);
    
         geom.setLocalTranslation(w.getPosition().addLocal(new Vector3f(0f, 0f, 0f)));
         rootNode.attachChild(geom);
     }
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    Waypoint wayPoint = navi.getNextWaypoint();
    if (wayPoint == null) {
    return;
    }

     Vector3f v = wayPoint.getPosition().subtract(enemy.getLocalTranslation());
     enemyControl.setWalkDirection(v.normalize().mult(10f));
     if(enemy.getLocalTranslation().distance(wayPoint.getPosition()) &lt;= 0.5f &amp;&amp; !navi.getPath().getEnd().equals(wayPoint)) {  //.equals() does not work because the position is     never exactly the same
         navi.goToNextWaypoint();
     }
    

    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }
    [/java]