Best way to set up Tag Penalty for Walls

I have a simple tower defense game with walls that units should go around to get to the towers and destroy the towers. However, if it takes too long to go around, they should try and go through the wall instead (I will implement the code to stop them and have them attack the wall and break it down, that’s not part of my question at all). I was thinking adding a tag penalty to the walls would be a great way to do this, I’ll set it very high and the units will only try and go through the walls if it is a really long way around.

I’m not sure what the ‘best’ or ‘recommended’ way to set this up is; the walls will all have their positions determined in advance, but I need a programmatic way of setting up the tag penalties that does not rely on fixed positions for walls. What I mean is the user can change the locations of the walls, so I can’t premake the level or anything, but when the wave starts the walls will not move after that.

I read through and watched the tutorials on tags and it seems that using the GraphUpdateObject to add a tag penalty for a certain region is the only way I could do this, and I wasn’t sure the best way to implement this solution. The walls are individual components, and there could be up to 250, is it performant to make each wall segment have it’s own GUO(up to 250) that has the tag penalty? Am I missing anything, or is there a better way to do this? Thanks in advance!!

Hi

Yeah, that will work just fine. Make sure that the updatePhysics field is disabled however.
Since the walls are only updating the graph once, it will not be a big problem.

If all walls only cover a single node, you can do this, which will be a bit faster.

 AstarPath.RegisterSafeUpdate (() => {
     var nn = NNConstraint.None;
     foreach (var tower in towers) {
         AstarPath.active.GetNearest(tower.position, nn).node.Penalty = 10000;
     }
}

Thanks so much for the reply!

It seems that adding a separate GraphicsUpdateScene object for each wall segment was making things slow down in my game by quite a bit, so I am interested in other solutions, although I haven’t tried it with updatePhysics disabled yet.

Your recommendation is a good one, I’ll try that. Coding question - where would I set the RegisterSafeUpdate() ? It looks like a class delegate I can set anywhere, so I could do it on startup from my GameController or something? Although I’m not new to programming, I’m new to Unity and C#, so thanks for the help.

Also, if you could point me to some good resources for Intermediate/Advanced scripting for your A* that would be great. I’ve noticed you mention that the beginner tutorial pathfinder is not optimal and should be improved, but I’m not sure where to go to learn how to improve it. As a C# noob, some of the syntax and your docs seem a bit unclear to me as to what I should be doing to proceed learning more about optimizing and customizing A*. Which classes and methods should be focused on for improvement for grid graphs in particular would be great so I can get a general grasp of the ideas I should be working with, thanks!

Ah, you said GraphicsUpdateScene instead of GraphicsUpdateObject. GraphUpdateScene has slightly more overhead since it is a component (but it uses a GraphUpdateObject internally), but it should not be very slow. After the initial update is done, it should have no effect on performance at all (except a very tiny amount of extra memory used by the component). Possibly what you were seeing were the gizmo drawing that caused performance problems. Gizmos in Unity can slow things down a bit if you are drawing a lot.

Yes, the RegisterSafeUpdate method is a convenience method to register a delegate which will be invoked when the pathfinding threads have been paused and it is safe to update the graphs (we don’t want to update the graphs while paths are being calculated at the same time in other threads).