Support Forum

Mass Updating of Grid Graph

Hi,

I have a grid graph and the “small” map in my game has it at 320x320 nodes. The user can paint the terrain in my game with a brush that is 10x10 world units and that is updating 50x50=2500 nodes every frame. The slowest parts of this update is RecalculateCell() which is doing ray casts for the heights and the capsule casts.

I have the height data in a heightmap and so i don’t need to do raycasts, even without this bit it’s quite slow. Am i able to parallelise any of these node updates with jobs in the GraphUpdateObject callback?

Thanks,

Hi

That’s a lot of updates every frame. I’d recommend that you at least do some batching to combine updates for say 10 frames and update the total bounding box that could have changed in those 10 frames (just do Bounds.Encapsulate).

You can also upgrade to the beta version which has significantly faster grid graph scanning (it uses burst and the unity jobs system, among other things all raycasts are parallelized). It is also possible to write your own grid graph rules (to for example read from a custom heightmap). See this tutorial: https://www.arongranberg.com/astar/documentation/dev_4_3_43_939d7455/gridrules.html

Hi Aron,

Thanks. I would definitely upgrade to the latest but I’m not not sure which Unity account i purchased it against and i can’t seem to find that. I have an internal Unity licence (because I work there) and i have a personal one.

Are you able to help with this? If i can sort that out I can atleast upgrade.

Thanks,

Ah ok I’ve found the account where i bought it.

Hi Again,

So since updating my graph updater object is no longer being run. I’ve had a go at debugging the package but can’t see anything obvious. Is there documentation on anything that’s changed in this regard?

Thanks

Ah so i’m supposed to implemented ApplyJob<>() it seems :). Is there an example of this somewhere?

Thanks,

So I’ve successfully got this working with ApplyJob. I only seem to get one ApplyJob callback though, i was hoping that it might divid the nodes to be updated over many threads.

Is this possible?

Hi

In that function you are supposed to schedule a job, not do the work itself. You can for example schedule a batch job if you want, to be able to parallelize it even more. You are passed an instance of a JobDependencyTracker (https://www.arongranberg.com/astar/documentation/dev_4_3_43_939d7455/jobdependencytracker.html) which you can use to schedule the job. See https://www.arongranberg.com/astar/documentation/dev_4_3_43_939d7455/ijobextensions.html. For example you can use myjob.ScheduleBatch (making sure to pass the dependency tracker).

You can find an example of the implementation in the GraphUpdateObject class.

Hi Aron,

Thanks. So at first glance ScheduleBatch is just about raycasting. I can avoid doing any raycasts at all because i already know the node heights from my heightmap. The work i am doing (incorrectly it seems) in ApplyJob is as follows:

		public override void ApplyJob<T>(T mapper, GraphUpdateData data, JobDependencyTracker dependencyTracker)
		{
			base.ApplyJob(mapper, data, dependencyTracker); 

			dependencyTracker.AllWritesDependency.Complete();

			TerrainGenerator generator = m_terrain.m_terrainGenerator;
			int courseSubTilesWidth = generator.GetCourse().GetDims().x * CourseCell.s_subTilesWidth;
			int heightMapWidth = courseSubTilesWidth + 1;

			for (int idx = 0; idx < data.nodePositions.Length; ++idx)
			{
				Vector3 position = data.nodePositions[idx];

				position -= new Vector3(0.5f, 0.0f, 0.5f);
				position += new Vector3(heightMapWidth / 2, 0.0f, heightMapWidth / 2);

				float height = GameStateManager.Instance.GetGameState().m_courseGameState.m_heights[(int)position.z * heightMapWidth + (int)position.x].m_height;
				data.nodePositions[idx] = new Vector3(data.nodePositions[idx].x, height, data.nodePositions[idx].z);
				data.nodeWalkable[idx] = !GameStateManager.Instance.GetGameState().m_courseGameState.m_occupancy[(int)position.z * courseSubTilesWidth + (int)position.x].m_occupied;
			}
		}

To speed this up I basically want to jobify the loop contents into batches without doing casts. One thing i couldn’t figure out here was how i was supposed to know where in the ‘data’ member i was indexing. I couldn’t get at the GridIndexMapper. Instead I did this based on knowing where the nodes would be in the scene relative to my terrain. It’s a total hack but works.

Can i just spawn myself some jobs without using the dependency tracker?

Thanks

Ah after a deeper look I can see more general batch scheduler in the base class.

Ill try this.

Thanks