Automatically creating penalties

Hi,
I’m building a game using a 2d tilemap and this brilliant asset. I want to make use of the penalties feature, but my maps are far too large and complex to manually build out each penalty zone. The penalties for each node should be defined by the tile on (or around I suppose) that node.
I’ve already made a script which does this, however it does so at runtime, which seems quite inefficient for what is a static map, and would like to be able to do that in the editor.
To sum up, I want to define penalty zones based on tiles in a tilemap.

As a bit of a side question, not as important as this main one but would be great to know, is it possible to use penalties, tags, or something similar to tell the seeker where to/not to path to. So somewhat similar to walkable, but the agents should be able to walk over those zones, just not have it as the destination?
Thanks!

Hi

If you scan the graph outside of editor mode you could run your script and then save your graph to a file (or use the graph cache feature). See https://arongranberg.com/astar/docs/editormode.html and https://www.arongranberg.com/astar/docs/save-load-graphs.php

I would recommend you to use the profiler first though, usually it is fine to do these kinds of things at the start of the game.

You could use GetNearest to check if a given destination has a specific tag/penalty before assigning that point as a destination for your character? https://arongranberg.com/astar/docs/astarpath.html#GetNearest. You could also use an NNConstraint with the GetNearest method to find the closest node which is in a specific tag mask.

Cheers for the quick response!
The graph saving would work perfectly, so thanks for that first of all! You’re probably right about the performance impact, but its nice to know that I can optimise it and its so simply to do so.

I don’t think I could search for a tag mask, as my script just sets the penalty directly on each node. I didn’t see a way to set the tag for each node rather than the penalty, but if thats possible its certainly the better way to go.
As for get nearest, I did think of this but the problem is I need to find a path with a destination on a tag, whereas just doing that would cancel the path completely if the destination isnt on the specific tag. Even if I could generate a different path every time (Im using fleepath), I would have to loop through it to find the correct path which would be difficult with how my script is setup, and moreso I’d rather just move to the wrong tag if moving to the specific one isnt possible, if that makes sense.

With penalties you set them like

node.Penatly = blah

with tags you do

node.Tag = blah

Ah. You are using the FleePath. To get the behaviour you are looking for you would need to duplicate the RandomPath.cs & FleePath scripts to create your own path classes and make some minor modifications to them. The RandomPath class checks if the current node is a valid node to stop at using the IF statements

if (currentR.G >= searchLength) {
	if (currentR.G <= searchLength+spread) {

You would need to modify them so that they also check if the node has the correct tag.

Ah, that makes perfect sense. I’ve tried making a start at that (I need to go to work in 5 minutes) but I’m getting a few errors on my new randompath script. All of the following are getting ‘Inaccessible due to its protection level’:

  • FailWithError
  • CanTraverse
  • CalculateHScore
  • searchedNodes

I’ve properly renamed the class and everything (at least to my knowledge, I can’t see any references to the old class name in there).
If it helps, unity gives a different message for each, saying ‘The name X does not exist within the current context’, with X being each one of them

Cheers!

I’m guessing you didn’t see my previous response (probably timezone differences), is there anything you’d suggest to fix the error?

Hi

Ah, right… Hmm. Yeah you might have to mark those things as not being ‘internal’ but instead ‘protected’.

That seems to have fixed it. For anyone else coming across this thread, doing this creates other issues on the other classes, because they are expecting an internal class and instead finding a protected one. So rather than changing each one to protected, change it to protected internal.

I also forgot to mention that I was getting an error with the FloodingPath override bool. Similar fix, change the class on Path to be protected internal and do the same on the 3 other classes that use it (RandomPath, ConstantPath, FloodPath). Finally, change the method on your next randompath script to be protected rather than internal, and theres no more errors.

I haven’t tried actually modifying the script yet to get the behaviour I want, so I’ll report back in a bit when I’ve tried that

It didn’t seem to have worked, I just used the following if statement and from what I can see it didnt really make a difference

if(currentR.node.Tag == 2 || currentR.node.Tag == 3 || currentR.node.Tag == 4)

However, there are so many factors that could be down to and it could take so long to figure out why I’m happy to just bookend it here. Penalty tags help to essentially do the same kind of thing, so I’m not too bothered.

Cheers for your help

1 Like