Can't get the AI to walk without strafing

First of all, I am sorry if this is a common question that has already been answered, couldn’t find something fitting.

I have a 3D world that is using Layered Grid Graph but I can’t make the AI to walk in a straight line when possible, usually I will get the AI to strafe a bit in random directions.
I am using the Simple Smooth Modifier to smooth the path as much as possible but if I over do it, the AI won’t be able to climb certain places due to path being too round.
Is there a way to make the AI always go in a straight line when possible?

Picture one - You can see that the agents can go straight to the Player but walk differently.

Picture two - The usual components I have on each agent.

Picture three - Tried to play around with Funnel/Raycast Modifier but the agent won’t be able to jump properly onto other blocks as the path is not going through the middle of the block.

I’m sorry again if it’s a common question but already tried most of the stuff here, would love any input.

1 Like

Hi

Maybe you want to use the Raycast modifier instead of the SimpleSmooth modifier. That modifier is intended to simplify paths to straighter lines. I’d recommend using graph raycasting on the raycast modifier (however that option is only available in the pro version).
See https://arongranberg.com/astar/docs/modifiers.php

2 Likes

Thanks for the fast reply!
I’ve tried doing it, while fixing the straight path problem it causes two others.
First off, the path is not always following the available path to the Player but rather returns a straight line. (as seen in the image below)
The second problem is the steering target is changing at a distance the closer you get to the jump location.

But if I use the regular Simple Smooth Modifier I get the correct steering target which allows me to jump when needed and it follows the right path to the Player. (Only downside is the messy path as I mention above)

Hi

Ah. Okay, so I think you might need a special case here. You really want the raycast modifier on flat ground, but you want to disable it when your character would need to jump.

So I would suggest this:

  • Open the RaycastModifier.cs script and find the ValidateLine method.
  • Add the code below to the start of that method
// Check if the y coordinate is the same (with a small error margin to account for floating point errors)
if (Mathf.Abs(v1.y - v2.y) > 0.01f) return false;

Also, I’d recommend that you change back the Seeker -> Start End Modifier -> Start Point/End Point snapping to ‘ClosestOnNode’, which is the default. Wit the ‘Original’ mode you may get issues when the target is outside the walkable regions of the graph.

1 Like

That’s perfect! Solved everything!
Thank you for the input and the quick responses!

1 Like

Awesome :slight_smile: I’m glad it works well for you now.

Also, if you feel like it, a rating and/or review on the unity asset store goes a long way to support the package even more :slight_smile:

1 Like

Hey!
Just noticed another issue there is using the raycast modifier.
When I and the agent are at the same height level but there is a climbable obstacle in the way,
the path line would be a straight line.


While it should be. (without the raycast modifier)




Still playing around with it to figure it but I would appreciate the help! :slight_smile:

Hi

Ah. Yeah I anticipated that, but I didn’t think it would be a problem for your use case.

It is relatively easy to fix that though. You can remove the earlier changes you made and instead do the changes I have listed in this diff: https://pastebin.com/MDXBiaiw
The earlier changes you made are a special case of these new changes. Previously it would only check if the start and end point of a candidate simplification line were at the same y coordinate, now it will also make sure that all points in between are at the same y coordinate.

1 Like

Not working, seems like it’s not reaching that part of the code as it’s stops at line 117

Line 117:

if(ValidateLine(null, null, p.vectorPath[0], p.vectorPath[p.vectorPath.Count-1])) {
// A very common case is that there is a straight line to the target.

My thought is that it enters this statement and therefore skips the else statement.
So, when the Player and agent are at the same y level, it’s going to count as a straight line and skip the diff you posted right?

Pretty sure I can enter the diff you posted into the ValidateLine function(if I got it right) and it would sort it but I want to keep it as efficient as possible so I would rather hear your opinion.

Thanks a lot!

P.S Sent you a message with the Raycast modifier script I am using.

Hey, any thoughts by anyone?

Ah. Missed that special case.
Commenting out that if statement should work well. Considering that most longer paths in your game will require some climbing, this will not affect performance really (because the special case would not apply that often).

Seems like it won’t work.
Commenting out that if statement would essentially make the Raycast modifier useless as now it acts as if the modifier is disabled (well almost).
First off, you would only get straight lines if you are standing relatively on the x/z axis. (picture 1)
If you stand diagonally you will get the curvy path again, same as without the modifier. (picture 2)

Regarding the jumping issue, if you stand at relatively on the x/z axis, the agent won’t jump over obstacles (picture 3).
But when you stand diagonally it would (picture 4).

So basically if I comment that if statement out it would mostly act as if the modifier is disabled.

Photos:

Again, I appreciate the time you put into this and I would ask for help without sitting on it for a while myself.
Wouldn’t checking the points.y in the ValidateLine function instead of at the ApplyGreed solve it?

Edit:
So, I discarded the diff you provided and then changed:

// Check if the y coordinate is the same (with a small error margin to account for floating point errors) if (Mathf.Abs(v1.y - v2.y) > 0.01f) return false;

To check every point in the points array the same way. Seems to work fine and shouldn’t be resource heavy, I hope.

1 Like

Hi

Yes, if you store that array as a variable that the ValidateLine method can access, then checking it in the ValidateLine method works well too.

What I meant above which might have been badly communicated was that you should remove only the IF part of the if statement, not the ELSE part, so that it would always execute the ELSE part.

1 Like

Yeah, That’s what I’ve done.
It reacted weirdly for some reason, maybe I’ve changed something without noticing.
Anyhow, I’ve passed the points ArrayList to ValidateLine and checked there, all works great now!

Thanks a lot for your time and help!

1 Like