Create NavMeshes for Panda AI within your game

Me and blender do not get along. I want to create my scene with code, not in an external 3D drawing software program. The ‘open blender, load your scene, do stuff’ seemed a needlessly convoluted way to make a navmesh. This sort of thing should be automatable, otherwise you need to manually bake a new navmesh every time you move a rock.

So I made a navmesh generator that can create a navmesh for Panda AI within your game code.
github NavMeshGenerator.py
github tests for NavMeshGenerator

I’ll summarize how it works in case you want to tinker with or create your own.

A navmesh is a collection of nodes and their connected neighbours. So if the AI wants to go from A to B, it looks for the shortest series of connected nodes and then follows that path.

To create a navmesh from your scene my generator places a collisionray and checks for a collision, if there is one, the node at that position is discarded.

The NavMeshGenerator is a class.
To generate a navmesh, you run the generate() function, which takes no variables. It only creates flat meshes in the XY plane at the moment, leaving gaps where it detected obstacles. So at the moment it’s only good for 2D navigation.

The generator has default values that can be altered. They are:

  • dirname for the directory where you want the navmesh to be saved
  • basename for the name you want the navmesh to be saved under. Do include the .csv file extension.
  • gridSize determines how many nodes there are in the navmesh. For example 10, creates a 10x10 100 nodes navmesh.
  • xstep is the distance you want to have between the nodes along the x axis.
  • ystep is the distance you want to have between the nodes along the y axis.
  • bottomLeftCorner determines where the navmesh fits in the scene. If you made your scene to be all positive x and y, you can leave it at zero. The navmesh stores xyz position data, it cannot be moved after creating. Just create a new one.
  • bitMask is the bitMask you want use for the collision testing to see where the navmesh needs to have gaps. Dont forget that you can easily combine bitMasks with the |. You will have to put your floors or ceilings on a different bit than the walls and obstacles, otherwise the ray will collide way too often and the navmesh will be empty.
  • scene is the nodepath you want to attach the collision ray to and traverse with the generator. It defaults to base.render when left on None.

edit: I am slowly working on some examples. Here’s some basic troubleshooting assistance:

  • Cant find source or destination: the start or target position is outside the grid and/or the xstep or ystep is too small or too rectangular. Try bigger squares first, then see if you can finetune it.
  • DESTINATION NOT REACHABLE MATE! Rarer error. Try a smaller xstep/ystep maybe?
  • It’s probably a good idea to store a reference to the aiBehaviors somewhere. setPythonTag for example.
  • Pathfinding obstacles are added and removed on the aiBehavior of the AICharacters.
  • The order you call the functions in matters, and the PandAI library will crash, sometimes without any message or warning at the slightest problem.
  • On the aiBehavior of the AICharacter (aiBehavior = aiChar.getAiBehaviors). First, initPathFind(navMesh), then add all the relevant obstacles, then call pathFindTo
  • The obstacleAvoidance feeler thingie seems to not apply to the pathfinding obstacles
3 Likes

That’s pretty cool, and something that I can see being useful to devs! Thank you for sharing it! :slight_smile: