Support Forum

How to Dynamicly generate the navmesh

Hi,

i am actually working on a procedural level in witch the whole level is build at start.
i have implemented A* easily, and made some tests, and i know it’s possible to do what i need during runtime. but how…

my problem is actually about the parameters pathfinder is providing, i tried with multiple grid to check differences and see witch can fit my needs, and finally i have the choice but none of them can be set to fit my generated level.

here is a screenshot of one level randomly generated:

as you can see the white square at the bottom left of the level is the pathfinder result.
it is always generated at 0,0,0 and never update the bounds of the level.

after manually modifying it during play, i can get it to work in few second, just by cliking “snap bounds to scene” and “scan”.

so i tried to invoke methods from script but i don’t see how to call them.
the only way i fund is by the script.UpdateGraphs(bounds,1) ;
and it will only generate around the defined size in the inspector and is not updated after i set the bounds limits.

my whole script is for playmaker:

Blockquote
[RequiredField]
[CheckForComponent(typeof(AstarPath))]
public FsmOwnerDefault owner;

	public FsmVector3 boundsCenter;
	public FsmVector3 boundsExtents;
	public FsmVector3 boundsSize;
	public FsmVector3 boundsMin;
	public FsmVector3 boundsMax;
	Bounds bounds;
	public override void Reset()
	{
		owner = null;
	}
	// Code that runs on entering the state.
	public override void OnEnter()
	{
		var GO = owner.GameObject.Value;
		var script = GO.GetComponent<AstarPath>();

		bounds.center = boundsCenter.Value;
		bounds.extents = boundsExtents.Value;
		bounds.size = boundsSize.Value;
		bounds.min = boundsMin.Value;
		bounds.max = boundsMax.Value;

		script.UpdateGraphs(bounds,1) ;
		//script.ScanAsync();
		
		Finish();

I fund the method i need is in RecastGraph witch is not monobehavior.
var graph = script.GetComponent();
so unity doesn’t like the way i want to call it

if i can get it, i can call
graph.SnapForceBoundsToScene();

and have a chance to fit to the level boundaries, and then scan it.

Hi

You can use

AstarPath.active.data.recastGraph.SnapForceBoundsToScene();
AstarPath.active.Scan();

See also https://arongranberg.com/astar/docs/accessingdata.html

there gut my colonel !
so now it works perfectly on the start of the scene, it cause the game to freeze a bit during the time to calculate navmesh.
how can i make it smoother?

You can use AstarPath.active.ScanAsync (coroutine) to calculate the graphs asynchronously.

See https://arongranberg.com/astar/docs/astarpath.html#ScanAsync2 for a code example.

I think i miss something important in the process.

I tried:

public override void OnEnter()
		{
			var GO = owner.GameObject.Value;
			var script = GO.GetComponent<AstarPath>();

			script.data.recastGraph.SnapForceBoundsToScene();
			/*script.Scan();*/
			/*script.data.recastGraph.Scan();*/
			/*script.data.recastGraph.active.Scan();*/

			//script.data.recastGraph.active.ScanAsync();
			//script.astarData.recastGraph.active.ScanAsync();
			//script.ScanAsync();
			script.StartCoroutine("ScanAsync");

			Finish();
		}

All the Scan methods are working but cause time calculation and slowdown the game.
All scanAsync() methods are doing the same “no-result” and the message alert:

No MeshFilters were found contained in the layers specified by the 'mask' variables
UnityEngine.Debug:LogWarning(Object)
Pathfinding.RecastGraph:CollectMeshes(Bounds) (at Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:770)
Pathfinding.<ScanAllTiles>d__50:MoveNext() (at Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:660)
Pathfinding.<ScanInternal>d__46:MoveNext() (at Assets/AstarPathfindingProject/Generators/RecastGenerator.cs:583)
<ScanGraph>d__142:MoveNext() (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1796)
<ScanAsync>d__141:MoveNext() (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1733)
AstarPath:Scan(NavGraph[]) (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1605)
AstarPath:Awake() (at Assets/AstarPathfindingProject/Core/AstarPath.cs:1275)

so i tried to add an Update :

		public override void OnUpdate()
		{
			var GO = owner.GameObject.Value;
			var script = GO.GetComponent<AstarPath>();
			foreach (Progress progress in script.ScanAsync())
			{
				//script.ScanAsync();
				Debug.Log("progression:" + progress.description + " - " + (progress.progress * 100).ToString("0") + "%");
			}
		}

But the same here, with or without it, it seems that it can’t find any meshes, but the bounds are set before, so they exist.

i also noticed a red cross at the moment it start the scanAsync() method, over the whole level.

I think i go it to work with asynch, cause i can get Progress now, but it looks it takes so much calculations to do that i waill have to make a loading screen before the game starts.