Okay, so now we need to go up into our tick function in the player controller player Tick.
Here it is.
So first, let's get our controlled pawn.
So a pawn controlled pawn equals get pawn.
And we can actually place this in an if statement.
So we only do this if we have a valid pawn.
And in fact, we could just check is valid.
That way we take care of the case when it's pending kill.
We could do that if we wanted to.
So just something to keep in mind.
But if we have a valid pawn, I would like the location on the spline that is closest to the pawn because
our pawn may not always be exactly on the spline.
It'll most likely not be exactly on the spline.
Our character will be slightly off from the spline.
I want the location on the spline so I'm going to make a const f vector called location on spline.
Now to get that, I take my spline and the spline has lots of functions that get things like this.
One is find location closest to world location and this requires a world location so we can use our
controlled pawn, get actor location and for coordinate space, I'm going to use world space.
So I'm going to use E spline coordinate space, double colon world.
So this vector is the location on the spline that's closest to the controlled pawn.
So now that we have that location, we can find the direction on the spline that corresponds to this
location.
So we can make another const f vector called direction and we can take our spline and call another handy
function, find direction closest to world location and we can use location on spline.
In fact, we could just use the pawns location right there.
That would work too.
And we can also use e spline coordinate space world right here.
So I could just pass in the controlled pawn location there.
But then you wouldn't know about this function.
So it's good to know about them.
And as soon as we have that direction, we now know which direction to move the controlled pawn.
So we're going to take our controlled pawn and add movement input passing in the direction.
And that's it.
Now, there are a couple other things We want to check our distance to the destination.
We want to see if it's within auto run acceptance radius.
So we're going to make a const float called Distance to Destination, and we're going to get our location
on spline, which we calculated up there, minus our cached destination.
So that gives us the vector from the cached destination to the location on the spline.
It gets the distance between the two.
I'm going to wrap that in parentheses and get length.
And then we can check this distance.
We can say if distance to destination is less than or equal to our auto run acceptance radius.
If it is, well, then we should no longer be auto running.
So we're going to set be auto running equal to false, and then we'll no longer auto run.
We'll stop.
So this is great.
This is going to take care of our auto running.
And this could be just refactored into a function called auto running or something like that.
So why don't we make a private function for that void?
We'll keep it simple and call it auto run.
So we'll go ahead and generate definition.
I'm going to cut this and stick it right up there next to the tick function.
Right under player Tick.
And I'm literally going to just stick this code into my auto run function and call auto run here.
That way we're not cluttering up the player tick function.
We're handling it here.
So the last thing to do is to see if this works and most importantly, see if it works in multiplayer.
So why don't we compile and launch?
Okay, so I'm going to press play and it looks like I'm just auto running, so that's not good.
So I think my auto running boolean should be set to.
Fall somewhere and it's not being set to false.
So we can fix that.
And of course, our auto run function is just being called in player tick whether we should or not.
So we can just check here in auto run if be auto running.
In fact, if not be auto running return that way we'll only auto run if we should auto run if be auto
running is true.
So let's try that again.
All right.
So we're going to try this one more time.
I'm going to click and hold That still works.
I'm going to click and release.
That works.
And we see the path points and I'm going to click on the other side of this pillar.
And it looks like we never stop auto running, but it did run around it, so that's good.
We stopped that time.
So I might have gotten a path point way off of the map somewhere.
But it looks like aside from that small complication.
It's working.
Let's try this in multiplayer with two players.
And on our client.
I see that holding it down will work.
But if I click and release, nothing happens.
And in fact, we don't even get those debug spheres.
Now, the reason for this is something that will trip you up if you forget this step or if you don't
know about it.
And that is that we have to go to edit and project settings and find navigation.
Navigation system specifically.
And check allow client side navigation.
Without this checked that function generating our path will not work.
But now that we've checked this, it should.
So try not to forget about this.
In fact, this is a good thing to write down if you're ever planning on generating a pathfinding path
on the client side, because that's what we need to do here for our client now, as soon as that happens.
Now it works.
So I can click and we can generate that path and move to it.
Great.
Now, why is it that we get our character running off into the distance?
Sometimes it's not every time, but if we click on the other side of something, it seems like we're
never quite getting that end point.
We're just running off into the distance.
Well, that's going to happen if we click on this particular actor, right?
If I click on it, we're not getting a point on the NAV mesh so I can click and we're really not going
to get a valid point on the mesh.
So we need to handle what happens when we click on something that's not on the NAV mesh.
Well, for one, if I click on this pillar, I kind of want to move to the point behind it as if the
pillar wasn't hit by my line trace.
Right.
So if I click.
See, I don't want that sporadic behavior.
I don't want undefined behavior.
If I click on this thing, I want it to be like my line trace from my cursor could not even see it.
Now, we can handle that in a number of ways.
The simplest way would be to take our static mesh here and just have it ignore any and all line traces
that are using the visibility channel.
So if I go down to collision here for Collision Presets, it's set to default.
We can change it to custom and we see that it's blocking.
All right.
But if we check ignore for visibility.
Now if I press play.
And I click on it, we'll go right behind it.
So what was happening was we were hitting that collision volume, the simple collision volume.
If I hit Tilde and type show collision, we'll see that it's a big block here.
So clicking on that was causing us problems.
Now that it's ignoring the visibility channel, we're good.
Now, there's still one slight complication, and that's when we click on an area that's not in our
NAV mesh bounds volume.
And that would be basically right here in the center.
If I click on that, you'll see that, well, it's trying to run, but it'll never actually get close
enough to cancel auto running.
So we do have a path and the last point in the path is right here, but the destination is right there
in the middle.
So an easy way to fix that is to simply take that last point in our generated path and set that to be
our cached destination.
That way, as we're checking to see if we should stop auto running, we're checking the cached destination.
If that's now that last point in the path, then we'll reach it.
So what we can do is after we get our path points, after looping through those path points, we can
reset the cached destination.
So we can say cached destination equals and we can get that path points array.
So we'll say path points and we'll index it at NAV path path points dot numb minus one as Num is the
number of elements and minus one gives us the last element in that array.
And that way as we're checking to see if we're close enough, we're now going to check to see if we're
close enough to the last point in the path, which we know is a reachable point because it was generated
by find path to location synchronously.
So now that we've added this one little line, we should now be able to click anywhere here and we'll
always run to a reachable destination.
So she won't be running off into the distance with no end.
So we can test this out by going up to the pillar and clicking at its base and we'll see that we reach
the last point, or at least close enough to the last point, and we'll never actually be running off
into the distance with some undefined behavior.
Okay, so we now have Click to Move and it works in multiplayer and it's looking great.
So now we're ready to move on.
We have a couple of things to fix and refactor and then we can start working on our actual gameplay
abilities, which is really exciting.
So I'll see you soon.