Movement logic without graph, because of high memory usage


#1

Hello,
I have been debugging memory usage, and realized that by cutting down my layered grid graph size from 750x750, to 250x250, I can save almost 1Gig of memory. I did not realize that Astar was was using so much memory, and was initially thinking it was being caused by me expanding the size of my terrain. Is there a way to reduce this memory usage?

At this point, I am also debating giving my seekers my own custom list of waypoints to follow, but was wondering if there are still parts of the Astar library I can use, to handle the movement from waypoint to waypoint, without the existence of a graph. I like the way that seekers take turns smoothly, for example.


Coroutine: MoveNext Causing Stutters
#2

That seems really high. Even when I stacked a lot of boxes to get a 1024 * 1024 layered grid graph with 5 layers I only got up to 0.68 GB memory usage. And a 1024 * 1024 graph contains 80% more nodes than a 750*750 graph.

So I can see a few possible reasons for why the memory usage is so high:

  • You are using a very high number of threads. Each thread requires a small amount of temporary data for each node in the graph.
  • You have a very high number of layers in your graph. Make sure you enable ‘Show Unwalkable Nodes’ under A* Inspector -> Settings -> Advanced to see all layers.
  • You are profiling in the Unity editor and you have ‘Show Graphs’ enabled. The mesh for rending the graph in the scene view uses a lot of memory. Make sure you hide the graph to avoid that extra memory usage.

There are also some ways you can save memory.

  • In the Optimizations tab, enable ‘ASTAR_LEVELGRIDNODE_FEW_LAYERS’ (only if you have 16 or fewer layers though).
  • In the Optimizations tab, enable ASTAR_NO_PENALTY if you are not using any penalties (tags do not count).
  • In the Optimizations tab, enable ASTAR_GRID_NO_CUSTOM_CONNECTIONS if you are not using any off-mesh links.
  • In the Optimizations tab, make sure that ASTAR_JPS is disabled (this is the default)
  • In A* Inspector -> Settings. Make sure ‘Heuristic Optimization’ is disabled (this is the default). Though enabling this can give you a really large speed boost, so it might be worth the extra memory usage.

#3

Thank you for the detailed reply! I was really worried about this last night, but your message has given me new hope that I can get this optimized again, even at the larger grid scale.

I only have 3 layers (floors) I want to use, so I went ahead and enabled ASTAR_LEVELGRIDNODE_FEW_LAYERS, ASTAR_NO_PENALTY and ASTAR_GRID_NO_CUSTOM_CONNECTIONS. ASTAR_JPS and Heuristic Optimization is disabled. I was only using one thread, although now I need to think about writing code to have it use more.

Couple issues/notes:

  1. I am seeing a red warning in Astar saying, “This define is not consistent for all build targets, some have it enabled some have it disabled.” Did it find more than one instance of Astar in on my scene? I’m only seeing one. I do see two pivot points on scene, when I select the Astar object in the heirarchy though. I wonder if I should just remake the object from scratch.

  2. I noticed that Scan on Awake was on, even though I move the graph after game loads, and rescan it manually. I turned it off, and am wondering if layeredGridGraph.Scan() is the correct way to manually scan, after layeredGridGraph.SetDimensions() call.

  3. Most importantly, I am still seeing a 14 second load time, with a 750x750x1 layered grid graph. This is according to Astar’s own scan processing time log message. Is this normal or is it taking too long? I can post a screenshot of my settings. Do I just need to turn on caching to fix this?

  4. If I click somewhere on the grid for my test seeker to move to manually, the whole scene freezes up for a split second, and then the seeker starts heading to the destination. I feel like the increased size is also causing calculations to take longer.


#4

Hi

Which version are you using?

2: Yes, that’s the correct way.

4: Is it only the first time or every time?


#5

Hi,

I am on version 4.1.16. Should I upgrade?

  1. It’s happening every time unfortunately.

Please note that I am also doing about 100 UpdateGraph calls right after scanning the grid, to place some starting objects on scene. Not sure how this affects the whole performance factor, when the grid is this large.

Update:

  1. Removing the IsPathPossible() call from my test seeker, seems to have done away with the stuttering. Is there a more performant version of this call? I do a GetNearest() on both the start and end position of the path, before making the call.

  2. I have switched to a static starting position, in order to be able to use the startup cache functionality. Is it possible to cache a dynamic position that may change from game to game? So if it does start in the same position and size as a previous cached version, it would use that?

Thanks!


#6

Are you using the overload with a tag mask? That one would be veeery slow on a huge graph, but the one without a tag mask is extremely fast.

Yeah, that could be a good idea for you. The 4.1.21 beta improved performance of layered grid graphs a lot.
Quoting from the changelog:

Not quite sure what you mean by a static starting position? Could you elaborate?


#7

I am indeed using the tag mask, as every item I place on the grid has an assigned tag. I have to use this, in order to mimic the path my seeker would take, no?

By static, I meant that whatever grid size and position is entered into the Astar prefab grid settings before the scene is started, stays the same afterwards. The alternative would be to set this programmatically, to suit different terrains. I could be mistaken, but when the caching system says “Startup” cached, it seems to me like it only caches what is there when scene first starts.

Will upgrade to the latest beta to check out the latest improvements. Hopefully, the new version will also get ride of the optimization setting errors I mentioned above as well. Thanks!


#8

Ah. It is actually possible to move the whole grid after it has been scanned using code.
You can use the GridGraph.RelocateNodes method to specify the new center, rotation etc.

Yes, that is correct. Is it not possible to wait for the path result to come back? For a graph that large I would actually not be surprised if the IsPathPossible method call takes longer than the path calculation itself.

Yes. That was also fixed in 4.1.21 I think.


#9

I could rewrite that code to have a seeker ‘wait’ to take their next action, until they get a response about whether the path is possible. I thought the IsPathPossible call basically did a subset of what my next StarPath call did, except without the movement.

I don’t call a get path function separately, so i’m surprised that the direct StartPath call works quicker. Wouldn’t it also need to do the same job of calculating if it can get to the destination? Or does it not stutter because it defers a lot of that work to other frames?

Just to make sure, are you recommending I get path separately before calling seeker.StartPath(), or are you saying to check the OnPathComplete() result?


#10

Updated to 4.1.22, but I unfortunately still see the warning underneath the optimization settings. When I click Apply, I see the following in the console log:

PlayerSettings Validation: Requested build target group (17) doesn't exist; #define symbols for scripting won't be added.
UnityEditor.PlayerSettings:SetScriptingDefineSymbolsForGroup(BuildTargetGroup, String)
Pathfinding.OptimizationHandler:SetDefineSymbols(Dictionary`2) (at Assets/AstarPathfindingProject/PackageTools/Editor/OptimizationHandler.cs:72)
Pathfinding.OptimizationHandler:DisableDefine(String) (at Assets/AstarPathfindingProject/PackageTools/Editor/OptimizationHandler.cs:91)
Pathfinding.OptimizationHandler:ApplyDefines(List`1) (at Assets/AstarPathfindingProject/PackageTools/Editor/OptimizationHandler.cs:140)
Pathfinding.AstarPathEditor:DrawOptimizationSettings() (at Assets/AstarPathfindingProject/Editor/AstarPathEditor.cs:419)
Pathfinding.AstarPathEditor:DrawMainArea() (at Assets/AstarPathfindingProject/Editor/AstarPathEditor.cs:376)
Pathfinding.AstarPathEditor:OnInspectorGUI() (at Assets/AstarPathfindingProject/Editor/AstarPathEditor.cs:255)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)


#11

Meh. Unity has deprecated some build target again. Which version of Unity are you using?
The warning is nothing to worry about though. I will make an update to the package to get rid of it, but it will not affect anything for you.

I mean that you just do a single path request and check the result in OnPathComplete.
The IsPathPossible call was originally for only when you don’t care about the tags. This method is extremely fast, it’s literally just a single line of code. The tag version was added due to popular demand, but it more of a convenience function than an efficient function. What it does is essentially just make a list of every single node that can be reached form the start node, and check if the end node is in that list. The path call can usually (in case the target can actually be reached) come to the conclusion that the target can be reached much faster because it uses the A* algorithm instead of listing every single reachable node. If on the other hand the end node cannot be reached, then the A* algorithm will also have to visit every single node it can reach in order to conclude it cannot reach the target. However in a path request it will all be offloaded to a separate thread, so it will be less of an issue.


#12

I am using 2018.2.4f1. Will need to upgrade that as well this week. Thanks!