GC when updating graph for doors with off-mesh links

  • A* version: 5.4.4
  • Unity version: 6.1

Here is some code that is run when players open or close doors:

GraphUpdateObject guo = new GraphUpdateObject(NavmeshGUOCollider.bounds) {
    modifyWalkability = true,
    setWalkability = State != (int)DoorState.Closed,
    updatePhysics = false
};

AstarPath.active.UpdateGraphs(guo);

// Set the doors off-mesh link to only affect the tag-specific graphs
ink.graphMask = GameController.Instance.Map.TagsGraphMask;

// Activate the off-mesh link when the door is closed
Link.enabled = State == (int)DoorState.Closed && !IsLocked;

// This seemed to be required to prevent path failed warnings on clients on game load. I guess it forces the graph to be updated immediately with the link changes made above.
Link.Apply();

And here is a deep profile screenshot showing the sources of GC:

Is there any way for me to avoid this GC? Doors can be opened/closed very often by players or AI creatures.

Hi

Those allocations are (I think) from internal delegates, and are a bit hard to avoid with the current architecture, I’m afraid.

Fortunately they should be very short-lived, and I suppose opening doors is not something that happens every frame?

Opening doors definitely doesn’t happen every frame, but as a multiplayer with 4 players and also many AI creatures there is lots of doors being opened and closed constantly. Any sort of GC here would most definitely be best avoided, so can we try to dig a bit deeper? :folded_hands:

I’m not sure exactly where the GC from within AstarPath.QueueGraphUpdates() comes from. There is a new there so that might be it.. but according to the deep profile shown above, there are 2 calls that create GC within the function for a total of 184B.

For NodeLink2.TryAddLink() is it possible to avoid the new calls there? That would be the reason for the GC. Alternatively, I can try to inherit from the NodeLink2 class and override Apply() then put my own cached logic in. But I feel like it’d be a bigger win for it to be done within the asset for everyone.

I was able to remove Link.Apply() by making sure the NodeLink2 component is disabled by default in the door prefab and then when it gets enabled via my code it seems to work fine.

The last thing in my own code that allocates is calling new GraphUpdateObject() every time. Is there some other approach we can take that would avoid this allocation?

That then leaves the AstarPath.UpdateGraphs() internal stuff which allocates almost 0.5k each time..