GraphUpdateScene not updating Tag and Tag display problem

I cannot seem to make GraphUpdateScene to work on my graph.

I have navmesh cuts using IsDual on my objects and I want to mark the cuts with specific tag. The debug tag display is totally blank:

With solid color display I can see the cuts correctly:

PS. Its on Unity 2018.3.1f

Hi

That’s odd… I’m not sure what could be happening. Does nothing show even if you enable the ‘Show Surface’ toggle in the graph settings?

Tags and navmesh cuts do however not really work well together. The reason is that as a navmesh cut moves around, it’s pretty much impossible to determine how the tags of the nodes should change as the new node boundaries do not line up with the old ones. If the node stays exactly the same after a navmesh cut update was made then the tag will be kept, but otherwise it will be reset to zero.

Yes, it does not shows even with show surface.

My cuts would be static once it has been made. It would actually be nice if the dual cut could tag the new nodes immediately.

How to control the order when the cut is made and the tag is applied with GraphSceneUpdate?

If you really want to be sure that you force it you could do something like this:

AstarPath.active.navmeshUpdates.ForceUpdate();
AstarPath.active.FlushWorkItems();
graphUpdateScene.Apply();

Which version of the package are you using?

I’m using newest version 4.2.4.

Strange. I will have to look into why that might not be working. Is it only the tag mode or is any other display mode not working?

Hi Aron,

It’s just the tag mode, regardless of the surface setting.

I will test now to see if the tags are actually set.

One more question, I noticed the TAG is uint. Does it mean I can assign arbitrary int from entire range? This would be very beneficial for me because I could tag the cuts underneath my buildings with unique int, it will help me with finding the building outline area.

Thanks for help and get well!

Hi

No, tags must be in the range 0…31. It is possible to modify the code to allow arbitrary integers though. Essentially you just have to change the property implementation to use a separate field for the tag instead of using bit-packing. By default it does not do this due to the increased memory usage.

I found the code for the mask:

		/// <summary>Start of tag bits. See: <see cref="Tag"/></summary>
		const int FlagsTagOffset = 19;
		/// <summary>Mask of tag bits. See: <see cref="Tag"/></summary>
		const uint FlagsTagMask = (32-1) << FlagsTagOffset;

It seems there is 12 bits for tag, so in practice I could store up to 2048 in the tag?

EDIT:

NVM I read the mask wrong.

1 Like

Hi Aron,

The Tag display is working:

However, I had to delay the GraphupdateScene application by 20s since game startup, I guess it’s due to all the graphs scanning and recalculation. My current code which works is the following:

            if ((AstarPath.active.isScanning
                 || AstarPath.active.IsAnyGraphUpdateInProgress
                 || AstarPath.active.IsAnyGraphUpdateQueued
                 || AstarPath.active.IsAnyWorkItemInProgress
                ) == false
                && Time.realtimeSinceStartup > 20)
            {
                var graphUpdate = GetComponent<GraphUpdateScene>();
                if (graphUpdate.enabled == false)
                {
                    graphUpdate.enabled = true;

                    AstarPath.active.navmeshUpdates.ForceUpdate();
                    AstarPath.active.FlushWorkItems();

                    graphUpdate.Apply();
                }
            }

Can you suggest how can I determine the cut has been applied to the graph and everything processed, so I can apply the graph update?

That’s odd. Once the graph is scanned you really shouldn’t have to wait at all. What happens if you remove the 20 seconds check?

The ForceUpdate + FlushWorkItems call will ensure that the cuts are done immediately, so when FlushWorkItems has run it is guaranteed that all navmesh cuts have been applied.

I went ahead and derived from NavmeshCut and introduced IsApplied field, so in the GraphUpdateScene I wait untill the corresponding cut is applied:

public class AdvancedNavmeshCut : NavmeshCut
{
	public bool IsApplied { get; set; }

	public override void NotifyUpdated()
	{
		IsApplied = true;

		base.NotifyUpdated();
	}
}
public class DelayedGraphUpdateScene : GraphUpdateScene
{
        public bool IsApplied;
        private bool workItemsFlushed = false;

        private AdvancedNavmeshCut[] _meshCuts;

        public void Update()
        {
            if (Application.isPlaying == false)
            {
                return;
            }

            if (_meshCuts == null)
            {
                _meshCuts = GetComponents<AdvancedNavmeshCut>();
            }

            if (IsApplied == false
                && workItemsFlushed)
            {

                Apply();

                AstarPath.active.FlushWorkItems();

                IsApplied = true;
            }

            if (IsApplied == false
                && workItemsFlushed == false
                && _meshCuts != null
                && _meshCuts.Length > 0
                && _meshCuts.All(m => m.IsApplied))
            {
                AstarPath.active.navmeshUpdates.ForceUpdate();
                AstarPath.active.FlushWorkItems();

                workItemsFlushed = true;
            }
        }
}

Everything is working fine for me with those classes, thanks for all the help.

1 Like

Cool but NotifyUpdated is an internal method. Were you modifying source of NavmeshCut.

Is it possible to achieve similar functionality without modification.

Yes, you need to modify the source code for AStar to achieve this. The modification is minimal so I don’t see this as a problem, all you need to do is change the access modifier to public for the method in following classes:

  • NavmeshClipper
  • NavmeshAdd
  • NavmeshCut

Also since my original post I noticed I need to delay the Tag update by 1 frame to resolve some strange problems (I modified my original post). Since then, I had no issues with this approach.

Ok thx. Anyway I’m baffled why we have to do all this to just cut a piece of geometry and change it’s tag. It sounds like such an obvious functionality that just adding NavmeshCut with GraphUpdateScene (without any region specified) should automagically do it’s work.

@koirat

Yeah. When the NavmeshCut class was written, I did not think anticipate that people would want to set weights and tags like that, even though in hindsight I should have thought about it. To do it properly I really should make tag adjustment built in to the NavmeshCut component as that would make the modification much cleaner and faster and more reliable. But as it is right now, this is unfortunately the workaround that has to be done.

Hello @aron_granberg

I’m again back with some of GraphUpdateScene issues :frowning: .

The graph updates that I place during runtime ends up updating nodes outside of it’s bounds, which were updated by other graph update.

Take a look here, this is my initial cut which is placed in the scene and is performed immediately on start:

When I place in game another cut+graph update, the vertices modified by original cut has it’s walkability and tag reset (marked with green):

Any suggestions how should I resolve this? The cuts+graph update which are there from the start seems to work fine, regardless how close they are, so I have a feeling there is probably some setup I can do that should avoid this situation.

EDIT:
So if I understand this correctly this seems to be caused by the fact, that tiles are reloaded when the cut happens, and nodes are destroyed as a result. They are then recreated, but the walkability and tag information is not propagated unfortunately.

This seems like a bug to me.