Start end modifiers

Hey, I am working on a voxel world project where a player can build.
So, inevitably players are going to hide behind walls and enemies would not be able to reach them.
To counter that, I want enemies to crowd the walls at different angles (depending on their spawn).
The enemies are set with Closest On Node for start/end modifiers so, they all crowd at the same spot of the wall as the AI Path gets the closest node available to the target.

Basically, I am asking if there is anything implemented to make the enemies go as highlighted in the picture or it’s something I need to code. (didn’t find anything about it but of course might have missed it)

I believe all nodes are given a default cost of 1000, which equates to one world unit. You could lower the cost of the nodes that are adjacent to your walls/obstacles to, say, 500. That should make the enemy agents prefer to stick to the walls, because it’s “cheaper” than walking on open ground.

You can turn on a visualization of the graph costs/penalties under the Pathfinding UI -> Settings -> Debug -> Graph Coloring -> Penalty.

You may also need to play with the “Start End Modifier” section of your Seeker (End Point Snapping) to get them to distribute around the walls in a way you like. Check out the “Exactness” enum documentation here: https://arongranberg.com/astar/docs/startendmodifier.html

Hey, I might have worded it poorly.
I want the enemies to stay close to the wall at different locations.

At the moment, the enemies would go to the same point no matter where they spawn, that point is the closest node to the player that is reachable by the enemies. (so they might go a full loop around the wall and stop the common point of all 4 enemies in the picture)
For example look at the picture, I want one to stop at the red circle and the other one to follow the red line.

I had a look at the “Exactness” earlier, doesn’t seem like there is something that fit.

I’m doing something similar in my project - I have buildings/resources that can be various sizes (1x1, 2x2, 2x3, 3x3, etc). For the 1x1 size, there are 8 adjacent “parking spots” that surround the central node which agents can occupy.

When an agent is has selected a building/resource as target, it then chooses the closest available parking spot and pathfinds to that node. Originally, I did what you did and just had them pathfind to the center of the structure and take their best guess as to where they should stop, but it did the same thing your game is doing. It wouldn’t pick the closest node between the agent and the target, it would pick the closest node between the target and the grid.

You could possibly go about this by using tags. When a player enters a structure, you could have it tag all the surrounding nodes with something like a “ParkingSpot” tag. Then you could use GetNearest() to find the nearest edge node between the agent and the structure. When the player leaves the structure, you would remove the tags and use different chase logic:

// Say that the "ParkingSpot" tag is #5 in your list
int ParkingSpotTag = 5;

NNConstraint constraint = NNConstraint.Default;
constraint.constrainTags = true;
constraint.tags = (1 << ParkingSpotTag);

NNInfoInternal info = MyGraph.GetNearest(transform.position, constraint);
GraphNode node = info.node;

// Pathfind to the closest parking spot on the structure's perimeter
MySeeker.StartPath(transform.position, node.position, OnPathFound);

Just make sure that both the “Ground” tag (probably Tag #0), and the “ParkingSpot” tag are both marked as Traversable in your Seeker component!

Hope this helps! Aron might have some magic knowledge that I don’t :wink:, in which case we can both learn something!

1 Like

Hey, first off all, thanks for the detailed response! :slightly_smiling_face:
Unfortunately I can’t use tags as it’s an open voxel world(like Minecraft) meaning Players can build whatever they want wherever they want so I have no way of knowing what is a structure.

Hey, any ideas anyone?

Hi

Currently there’s no proper implementation of this in the package.
I have been sketching on something which would be able to trade-off increased distance to the goal from where it will end up, and increased walking distance, but currently I don’t have anything.

However a heuristic which works surprisingly well in many cases is to simply tweak your target position slightly depending on where the unit is. Simply move the target position a small amount towards the agent’s position before searching for a path, this will break ties in a nice way.

image

1 Like

I was using an approach very similar to this before I jumped to my formalized “parking spots” solution.

You should be able to break ties like Aron is saying with something like this:

Vector3 targetPosition = MyTarget.transform.position;
Vector3 myPosition = transform.position;

// This nudges the end position slightly towards the agent, breaking ties when
// the target is exactly centered inside of an unwalkable/untraversable/off-grid area
// Tweak the "step" value of 0.5f to suit your use case
Vector3 targetHint = Vector3.MoveTowards(targetPosition, myPosition, 0.5f);

MySeeker.StartPath(myPosition, targetHint, OnPathFound);

See: https://docs.unity3d.com/ScriptReference/Vector3.MoveTowards.html

1 Like

Thanks for both of yours input :slight_smile:
It would definitely work but as you guys mentioned only if the Player is centered in the middle.

However I did get an idea out of it.
(This is purely a thoery, haven’t read enough from docs to know yet)

Because of the fact that every section has to be layered/colored differently, I think that they will be stored in different lists.
So if I use the node list that the Player is in to get the closest node to the Agent in that layer (which would be the red circle) and only then I would check for a reachable node closeby, I would be able to move the Agent to said node (which would be at the green circle).
So, it would result in the yellow dotted line as in the picture.

Sorry for the low quality image, attempted to do it from the phone.