Performance issues after switching from CharacterControl to BetterCharacterControl

Hi,

I’m fairly new to jme3, and try to implement a dynamic labyrinth the user navigates through. It worked quite well with the CharacterControl according to the tutorials from the documentation. But for some functionality I switched to the BetterCharacterControl. Since then, the performance dropped dramatically (before: 100s of frames per second, now 3-4 frames per second).

What could be the reason for this issue?

I already tried to optimise according to what I found, i.e. ensured that the labyrinth itself is static, using GeometryBatchFactory.optimize() on it, using a CompoundCollisionShape via CollisionShapeFactory.createMeshShape(), but nothing really helped.

The labyrinth itself is automatically generated and built by using Box geometries, each box representing one wall (it’s really just a first experiment with jme).

Here’s the code by which I add the labyrinth to the physics space (assuming collision control is the issue):

    CollisionShape mazeShape = CollisionShapeFactory.createMeshShape(this.maze.getRootNode());
    this.landscape = new RigidBodyControl(mazeShape, 0.0f);
    this.maze.addControl(this.landscape);

This is the character control setup:

    this.playerNode = new Node(PLAYER_NAME);
    this.playerNode.setLocalTranslation(cam.getLocation());
    this.app.getRootNode().attachChild(this.playerNode);
    this.playerControl = new BetterCharacterControl(1f, 4f, 10f);
    this.playerControl.setJumpForce(new Vector3f(0, 10, 0));
    this.playerControl.setGravity(new Vector3f(0, -20, 0));
    this.playerNode.addControl(this.playerControl);

And finally it gets added to an bullet app state:

    bulletAppState = new BulletAppState();
    stateManager.attach(bulletAppState);
    bulletAppState.getPhysicsSpace().add(this.landscape);
    bulletAppState.getPhysicsSpace().add(this.playerControl);

Anything obvious I did wrong?

Well it is actual physics while the old character is basically just a ray test. I’d suspect you will get this even if you only drop a box in your level, not just with the better character. I guess the ground mesh is too large (partition your mesh) or too detailed (try using a lowpoly version of the mesh for physics).

Thanks for the fast reply - that’s quite likely. I also reduced the size of the labyrinth to a really low number, and got the framerate only cranked up to ~ 7 frames per second.

I currently use boxes to build the labyrinth - think ascii graphics, and if there’s a wall, there sits one box generated as follows (also according to tutorial):

    Box box = new Box(1,1,1);
    Geometry wall = new Geometry(name, box);
    wall.scale(1.5f);
    Material mat = new Material(this.assetManager, "Common/MatDefs/Light/Lighting.j3md");
    mat.setTexture("DiffuseMap", this.assetManager.loadTexture("Textures/Terrain/Pond/Pond.jpg"));
    mat.setTexture("NormalMap", this.assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));
    mat.setBoolean("UseMaterialColors",true);
    mat.setColor("Diffuse",ColorRGBA.White);
    mat.setColor("Specular",ColorRGBA.White);
    mat.setFloat("Shininess", 1f);
    wall.setMaterial(mat);
    return wall;

As the labyrinth is random, I cannot import an external mesh. Most likely this is a stupid way of building it, what would be the right way?

If it is the right way, how can I partition the mesh / define a lowpoly version of it for physics (I thought that would be what CollisionShapeFactory.createMeshShape() does).

Oh my, thats not good. So you basically have lots of single boxes (i.e. meshes) and then create the shape using the collision shape factory? That will create a compound shape from single meshes which is surely the most inefficient type of collision shape. Read up on how to create one mesh for your level, make it not have faces inside (i.e. voxel world knowledge I suppose), partition it and then create your collision shape, best manually.

Another option, since your game currently consists of boxes is actually using box collision shapes. Depending on how your game is set up that might be a solution as well.

Game development isn’t always intuitive, the important thing is what is coming out on the screen and that is often smoke an mirrors :slight_smile: That house crumbling isn’t physics, that block world isn’t made out of boxes, the cake is a lie etc. :wink:

1 Like

Yes :slight_smile:

I was already quite impressed that this very basic approach was performing quite well with the CharacterControl - but if that does Raytracing only, it’s understandable. I was just in high hopes after the first great result …

I’ll try to find some documentation on dynamic mesh generation and try to fiddle myself through. Do you happen to have any recommendations/starting points for reading?

Quick search showed: https://jmonkeyengine.github.io/wiki/jme3/advanced/custom_meshes.html and some discussion threads.

Apparently, the issue was something else entirely - even after removing the entire labyrinth, the performance would drop drastically. I could solve it though by detaching the intro animation cinematic from the application manager - previously, I just disabled it via this.setEnabled(false);. Apparently, the lingering app state created a tremendous overhead.

Is that expected behaviour? I could imagine that sometimes one wants to keep multiple app states in parallel for easy toggling between them?

You can have hundreds of app states without issue.

…but just one BAD app state could cause problems.