A* Pathfinding Project

NavMesh Cut moving entire navmesh bounds


#1

I have a navmesh which is generated with local coordinates in the vertices that correspond to it’s world position. This is because I have a single instance of Astar Path in the scene sitting at (0,0,0). My navmeshes are all saved as .bytes files in the resources folder.

At runtime, I’m loading and unloading the navmeshes dynamically depending on where the player is in the world. My code for loading the .bytes files is as follows:

	private IEnumerator LoadNavmesh(string path)
	{
		ResourceRequest resourceLoadRequest = Resources.LoadAsync(path);
		yield return resourceLoadRequest; // wait until ready
		var textAsset = (TextAsset)resourceLoadRequest.asset;
		if (textAsset != null)
		{
			AstarPath.active.data.DeserializeGraphsAdditive(textAsset.bytes); // appends to graphs 
		}
		else if(Application.isEditor)
		{
			Debug.LogFormat("Failed to load navmesh asset from the path '{0}'", path);
		}
	}

This all works wonderfully, however, I need to incorporate navmesh cutting for destructible gameobjects which should only block enemy movement until the player or enemy breaks them, for example, barrels. Upon adding a single instance of the NavmeshCut script to one of my barrels and running the game, my navmesh suddenly shifts it’s entire bounds to fit the white bounds defined by the AStar Path script.

Here is an example of the difference between the way my navmesh appears with and without the navmesh cut script on a single object.

So it appears that something in the NavmeshCut script is re-centering the navmesh to fix the current center of the AStar Path instance. Is this a bug in the framework or am I missing something?

Thanks in advance.


#2

Hi

I cannot seem to replicate this bug. Which version of the package are you using?


#3

Thanks for the response, same problem in 4.2.2 and 4.2.5. I’ve created a sample project which contains the script I use to generate the navmesh .bytes files and the script that I use to load the .bytes files at runtime. In my sample, for simplicity purposes I’m extracting the mesh data from a Unity Plane primitive using the following function:


	public static bool CreateNavMesh(MeshFilter meshFilter, string name)
	{
		string path = string.Format("Assets/Resources/{0}.bytes", name);

		Mesh tempMesh = new Mesh
		{
			name = name,
			vertices = meshFilter.sharedMesh.vertices.Select(x => meshFilter.transform.TransformPoint(x)).ToArray(), // apply world position to mesh in order to ensure navmesh loads properly at runtime  
			triangles = meshFilter.sharedMesh.triangles,
			normals = meshFilter.sharedMesh.normals,
			uv = meshFilter.sharedMesh.uv,
			tangents = meshFilter.sharedMesh.tangents
		};

		if (AstarPath.active.data == null) AstarPath.active.data = new AstarData();

		AstarPath.active.data.FindGraphTypes(); // forces the internal code to populate the graphTypes array to avoid an intermittent object ref exception in AddGraph

		var graph = AstarPath.active.data.AddGraph(typeof(NavMeshGraph)) as NavMeshGraph;
		graph.sourceMesh = tempMesh;

		AstarPath.active.Scan();

		// important - clear the mesh after Scan and before SerializeGraphs to prevent hang that occurs loading this asset at runtime.
		// see http://forum.arongranberg.com/t/astarpath-active-data-deserializegraphs-textasset-bytes-very-slow/5886/3 for more info.
		graph.sourceMesh = null;

		// guid's are not automatically generated, so assign them here before saving to file
		foreach (var g in AstarPath.active.data.graphs)
		{
			if (g != null && g.guid == Pathfinding.Util.Guid.zero)
			{
				g.guid = Pathfinding.Util.Guid.NewGuid();
			}
		}

		var serializationSettings = Pathfinding.Serialization.SerializeSettings.Settings;
		serializationSettings.nodes = true;
		uint checksum;
		var bytes = AstarPath.active.data.SerializeGraphs(serializationSettings, out checksum);
		System.IO.File.WriteAllBytes(path, bytes);

		AssetDatabase.Refresh();

		EditorUtility.DisplayDialog("Complete", string.Format("The Navmesh was successfully saved to '{0}'", path), "Ok");
		return true;
	}

Here’s a dropbox link to a unitypackage for this sample project, should be very easy to reproduce.

  • import the package to an empty project

  • open the SampleScene

  • press play
    Notice the position of the Plane.bytes navmesh
    (this is the shifted position)

  • press stop

  • disable the Navmesh Cut component on the NavmeshCutCube object

  • press play
    Notice the position of the Plane.bytes navmesh
    (this is the expected position)


#4

Hi

I figured out what the problem was!
I have uploaded version 4.2.6 which fixes this bug.

Thanks for reporting it!


#5

Awesome, I’m relieved to hear it wasn’t a hard limitation due to my logic, thanks very much for promptly fixing it too!!


#6

Bummer, just tested it in my production project and my sample I gave you with the new changes in 4.2.6 and it’s still an issue in both. Any chance you left something out of the package?


#7

Hi

Make sure you re-save your graph. As the bug was with the saving code, loading a previously saved navmesh graph will still show the same issue.


#8

Yup, that fixed it, sorry I didn’t realize that was necessary, thanks for the fix!!