Penalty areas in a procedural environment

Hi thanks for the great project, its truly indispensable. Im just experimenting with it and have a query about the use of penalty areas.

I have a map which is procedurally generated by the user, the only constant being a plane (water) set at a fixed level. The water is traversable when certain conditions are met but for the most part it is to be avoided.

What would be the best way of handling this situation? Obviously using GUO points is not feasible, so is it possible to set the whole object itself as a penalty area by tagging it? or is it possible to exclude all Y coordinates below a certain level from a path call? Are the texture options in pro able to achieve this?

btw i have experimented with having a second map for just the water but this seems to affect the bots strangely e.g. stopping and losing the path, or partially retreating and spinning around before continuing.

Thanks for any pointers

GJ

You could offset the graph so that the Y level is at the same level as the water. Then check the Unwalkable If No Ground option in the grid graph settings. That would make all nodes below a specified Y coordinate unwalkable effectively.

Thanks for your swift reply, not sure I fully understand though, I do want to path the water under certain situations, but doesnt your suggestion make that impossible?

Perhaps I should have said that the water has a collider attached, so is effectively a solid surface.

Ah, sorry, missed that part.
What exactly are the certain situations? That would matter quite a lot for which solution is the best one.

My thinking at the moment is just by setting a simple character attribute to true, so for example if ‘CanSwim = true’ the character can factor that into their route, albeit with a penalty applied to that section.

Would it be possible to discriminate this way using the additional texture options in pro? I intend to buy regardless but it would be nice to know if its possible.

Sorry, that is not possible… Or well, not without scripting.
What I think is easiest right now is to write a small custom graph update object which will set all nodes below a specified Y value to have a specific tag. That tag can then be used to restrict units from walking there.

`
using Pathfinding;

public class WaterGUO : GraphUpdateObject {
public float ylimit = 0;
public override void Apply (Node node) {
if (((Vector3)node.position).y <= ylimit) {
node.tags = 1; //Set to use tag 1 (default tag is tag 0)
}
}
}`

WaterGUO guo = new WaterGUO (); guo.bounds = new Bounds (....); //Should cover the entire world guo.ylimit = 5; //Y limit of the water AstarPath.active.UpdateGraphs (guo);

Now you can specify which units can swim by changing the ‘enabled tags’ on the seeker component (or set the enabledTags field on the Path object if you are not using a Seeker).

That is absolutely phenomenal it works a treat! Also added:

node.penalty = (uint)(node.penalty+addPenalty);
and

guo.addPenalty = mywaterpenalty;
A thousand thank yous sir!

Great that it works. But a tip. you can set penalties for individual tags on the Seeker component as well. Seeker -> Tag Penalties. So you don’t need the node.penalty statement there if you use the same tag for every node.