GhostControl framerate drop

Hello guys,
I’m currently working on the AI of my game. I want the NPCs to follow the player within a certain radius. To do that, I attached a (pretty large) GhostControl to my player. Now I wanted to simulate hearing (when the player shoots and a NPC is inside the GhostControl, he moves to the position where the player shot), but the problem is that the framerate is dropping from about 1000 fps to <60 fps. Is there a better way to do this? I somehow need to check the radius but apparently a GhostControl with that size (radius ~50f) is too difficult to calculate. Here’s the code I’m using:
[java]package net.softwarepage.fearkill;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.GhostControl;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
*

  • @author Mathias AppState managing the AI of the small enemies
    */
    public class AIState extends AbstractAppState { //TODO: wenn nah, wenn gehört

    private Main app;
    private BulletAppState bulletAppState;
    private Map<Spatial, AnimChannel> smallEnemies = new HashMap<>();
    private ArrayList<Spatial> followers = new ArrayList<>();

    public AIState(Main application, BulletAppState bas) {
    app = application;
    bulletAppState = bas;
    }

    @Override
    public void initialize(AppStateManager stateManager, Application application) {
    super.initialize(stateManager, application);

     Spatial t1 = app.getAssetManager().loadModel("Models/skeleton.j3o");
     BetterCharacterControl t1Control = new BetterCharacterControl(1f, 4f, 30f);
     t1.addControl(t1Control);
     app.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(t1Control);
     t1Control.warp(new Vector3f(-10f, 0.2f, 5.0f));
     t1Control.setGravity(new Vector3f(0f, -30f, 0f));
     t1.setUserData("Health", 20f);
    
     Spatial t2 = app.getAssetManager().loadModel("Models/skeleton.j3o");
     BetterCharacterControl t2Control = new BetterCharacterControl(1f, 4f, 30f);
     t2.addControl(t2Control);
     app.getStateManager().getState(BulletAppState.class).getPhysicsSpace().add(t2Control);
     t2Control.warp(new Vector3f(0f, 0.2f, 5.0f));
     t2Control.setGravity(new Vector3f(0f, -30f, 0f));
     t2.setUserData("Health", 20f);
    
     AnimChannel channel = getChannel(t1);
     AnimChannel c2 = getChannel(t2);
    
     app.getEnemies().attachChild(t1);
     app.getEnemies().attachChild(t2);
    
     smallEnemies.put(t1, channel);
     smallEnemies.put(t2, c2);
    
     app.getRootNode().attachChild(app.getEnemies());
    
     GhostControl ghostControl = new GhostControl(new SphereCollisionShape(50f));
     app.getPlayer().addControl(ghostControl);
     bulletAppState.getPhysicsSpace().add(ghostControl);  //Without the line I have about 2000 fps; with it about 30
    

    }

    private AnimChannel getChannel(Spatial s) {
    Node n = (Node) s;
    Node metarig = (Node) n.getChild(“metarig”);
    Node pelvis = (Node) metarig.getChild(“Pelvis”);
    Node polySurface1 = (Node) pelvis.getChild(“polySurface2.006-entity”);
    Node polySurface2 = (Node) polySurface1.getChild(“polySurface2.006-ogremesh”);
    AnimControl control = polySurface2.getControl(AnimControl.class);
    AnimChannel channel = control.createChannel();
    return channel;
    }

    public AnimChannel getAnimChannel(Spatial s) {
    return smallEnemies.get(s);
    }

    public void remove(Spatial s) {
    smallEnemies.remove(s);
    followers.remove(s);
    bulletAppState.getPhysicsSpace().remove(s.getControl(BetterCharacterControl.class));
    }

    public void setFollower(Spatial s) {
    if (!followers.contains(s)) {
    smallEnemies.get(s).setAnim(“Walk”);
    followers.add(s);
    }
    }

    public void shotAt(Vector3f position) {
    }

    @Override
    public void update(float tpf) {
    for (Spatial s : followers) {
    moveToPlayer(s);
    }
    }

    private void moveToPlayer(Spatial s) {
    BetterCharacterControl b = s.getControl(BetterCharacterControl.class);
    Vector3f enemyDirection = app.getPlayer().getLocalTranslation().subtract(s.getLocalTranslation()).normalizeLocal();
    enemyDirection.multLocal(4f);
    enemyDirection.setY(0);
    b.setViewDirection(enemyDirection);
    b.setWalkDirection(enemyDirection);
    }

    @Override
    public void cleanup() {
    super.cleanup();
    //TODO: clean up what you initialized in the initialize method,
    //e.g. remove all spatials from rootNode
    //this is called on the OpenGL thread after the AppState has been detached
    }
    }
    [/java]

Maybe I could somehow just calculate everything that is above the terrain (the collisionshape is also under the terrain) or something like that… But otherwise I really don’t know how to solve this.

Just check the distance of the objects to the player?

1 Like

Sometimes the simplest solutions are the best facepalm
Thanks, Normen!

1 Like