Support Me on Patreon

Tuesday, April 9, 2019

Navmeshes and YOU!

Navmeshes and YOU!



Godot 3.1 tutorial

You should be familiar with the basics of the Godot Engine.
If you cannot make a moving character this tutorial may be too advanced.

This does not cover gridmaps, tilemaps, or 2D maps. Some of this might apply anyway though.



Chances are that you've looked at the navigation demos for godot. It shouldn't matter if you have, but it can help.
That demo just has a single navigation mesh. This will cover tips when you have more than one navigation mesh.
Let's look at some basics.

A navigation mesh, or navimesh, is basically a path that objects/NPCs/enemies can use to navigaet around a map.
Navimeshes can be generated from scenes or existing meshes. I prefer to model my own navimeshes and create them from a mesh instance.
Just add a mesh instance and set the mesh you want to make a navimesh from.
Select the mesh instance and use the mesh button in the top center of the 3D viewport.
Choose Create Navigation Mesh and move the navimesh where you want it, or save it to a file.


If you select a navigation mesh node you can bake a mesh from a similar menu.
You must have a new navmesh to do this.
I won't be covering this as I've never done it satisfactorily.



The navigation node is the powerhouse of path-finding. It can be used to generate paths.
All you have to do is add it. Here comes the complications.

Let's go over the problems you might find working with navigation nodes and some solutions.

Navimeshes must be children or grandchildren of the navigation node. Any deeper and they won't work.
If your scene is comprised of smaller scenes, this can be a problem.
You can add the navimeshes to a single group and make them direct children of the navigation node.

*Since godot gets direct references to nodes, changing their parent is relatively safe.
**You should be able to do this for most nodes, but be careful if you rearrange too many nodes.
***I haven't tried this with weakref()

This script is a bit of a hack, but it works well:

func reparent_by_group(group):
    navNodes = get_tree().get_nodes_in_group(group)
    for i in navNodes:
        var gPos = i.get_global_transform()
        i.get_parent().remove_child(i)
        self.add_child(i)
        i.transform = gPos
       
    print(self.get_child_count())
    pass

   
*I add pass to all my functions since I sometimes write numerous functions at a time.

Let's look at path generation

get_simple_path( Vector3 start, Vector3 end, bool optimize=true )

This creates an array of Vector3s to generate a  "path". Running it too often causes lag.
The start should be the NPC's translation or transform origin (get_transform().origin)
End should be a Vector3. Using the translation or transform origin of a node is a fine idea.
Travel to each point by using the look_at( Vector3 target, Vector3 up ) function.
Make a variable to keep track of which point you are moving to.
Add to the variable when you get close to the point. Use the Vector3().distance_to( Vector3 b ) function.
Again, NPC translation or transform origin is acceptable for the first Vector3.
When you run out of points, regenerate the path. Keep this up until you are near your goal.

If you are using node positions to navigate to, there are a few things to watch for.
Any nodes in nested scenes (child,grandchild) will cause the NPCs to converge around the map center or similar area.
Using get_global_transform().origin to generate paths caused lag.
Reparenting the nodes is a 'safe', simple option. Be sure to apply any groups or modifications to the nodes before reparenting them.
You shouldn't have to rename the nodes, the engine seems to do it automatically.

That should fix the majority of the problems you'll come across.

Working with multiple navigation meshes:

It may not be feasible to model one large navimesh for everything.
Building a game from numerous smaller scenes or reusing assets can complicate things.
You can use several navimeshes, but there is one thing to remember.

The meshes should have faces that line up perfectly.





Snapping vertices to the 3D modeling grid, and using snapping in Godot, will help.
As long at two meshes have faces that are vertex-perfectly aligned a path can be made including both meshes.
Any gaps, overlaps, or misaligned vertices can cause problems or mistakes.

Just make sure things align like a puzzle and everything will work well.



No comments:

Post a Comment