Before you go ahead and build yourself a full-blown waypoint system, you should probably know it's
already available in Unity.
So we've built our own little waypoint circuit
but now I'm going to show you what Unity has available in it for you.
So if you grab the code that I've included as a resource with this lecture, inside you'll find a
WaypointCircuit and a WaypointProgressTracker script and drag-and-drop those into your project.
These two files I have gotten from a download and import of the Utility package.
So it's under Assets > Import Package > Utility. That will bring in a folder called Standard Assets
and in that, somewhere, you will find these 2 scripts but I've included them so that you can quickly
add them and I'll show you the difference that you get using these.
First of all, there's a waypoint circuit and this will set up what we've achieved with an array and
these balls, but you'll still need to have the balls in there because they are waypoints.
So first, in the Hierarchy, Create Empty and we will call this our WPCircuit. To WPCircuit,
drag-and-drop the WaypointCircuit script, then get all of the spheres that you're using for your waypoints,
collect them up and drag-and-drop them so that they're 'child objects' of WPCircuit.
Now select the parent (the WPCircuit). Over in the Inspector, where you've added that code, you'll see a button
that says [Assign using all child objects]. If you click on that, it will create an automatic waypoint
out of all of your objects.
It will also link them up with a nice curve (which we can't see because my spheres are slightly under
the ground).
If I just lift those up, you'll see this circuit being drawn in the scene and you can see very easily
from that that you have a circuit and none of the waypoints in the wrong order for being
a complete circuit.
If you want to change the order they appear in, over in this Waypoint Circuit component that you've
added on to there,
let me grab the second one and I'll move it up and you'll see the result.
Now that Sphere(1) is the first one and Sphere(0) is the second one, you're going to get this crossover
and that might be what you want.
That's fine.
You can also grab hold of your waypoints and move them manually around as well, to change the particular
order of your circuit.
So they're the 2 things you should be aware of in setting up the circuit.
I'll just leave it crossed over there for a little bit of interest.
At this point, if you want to keep using your WaypointFollow script that we've already written on your
tank, then you need to update it to use the new waypoint circuit, instead of the individual spheres
in the game object array that we had.
So let's take a look how we would update the script. Back in the WaypointFollow, instead of this
public GameObject array at the top,
we now grab hold of the circuit itself.
Now that circuit is a WaypointCircuit type and it's in the namespace UnityStandardAssets.Utility because
remember I said that it does come in the Utility import
if you bring it down from there, so make sure that you declare it like that. It's going to be public, so that we
can tell it where the circuit is and drag and drop it in the Inspector.
The rest of the code is ok up here. In the Start,
you won't have to get your waypoints with a FindGameObjectsWithTag any more.
So we can comment that out. Down in the LateUpdate where we're getting each waypoint and
then turning towards it and moving towards it,
we just have to change our reference to what we're getting. So instead of the game object indexed by current
waypoint, we're getting the current waypoint from the list of waypoints that comes from the circuit.
So the first thing we do is check the length of the circuit.
So instead of waypoints.length that we had before, it's now
circuit.Waypoints.length
and when we get our goal, we're getting the circuit.waypoints[currentWP].position.x so
the transform has gone in here
because these waypoints have the positions straight out from there, you don't need the transform.
So just be sure that you haven't got that. Again, if you're in 3D space and you want to use the z
for the waypoint as well,
go ahead...put it in here, instead of the height of your character.
The other thing you need to change is just down inside the direction.magnitude part where we're
testing if we've run out of waypoints and we're going back to the beginning again, we need to get the
circuit.Waypoints.length not waypoints.length that we had before.
So save that and switch back into Unity and press Play
and you'll be able to watch your tank move around your circuit of waypoints. So it's the same waypoints
we had before, but now we're just organizing them using Unity's WaypointCircuit code that it brings
and it's very useful because first of all, it gives you the visualization of what your circuit is going
to look like in the scene
and it allows you to reorganize these waypoints. Using this method,
you'll notice that the tank does not stick to the yellow line. The yellow line
in this case, is just a guide for where the circuit is and which waypoint is connected to which other
waypoint.
Now we're going to bring the WaypointProgressTracker into play.
So this is the other Unity created script that comes in Utilities. It's going to be attached to our tank.
Select the tank in the Hierarchy and remove the WaypointFollow script that we created. Then instead,
in the Inspector, you want to drag-and-drop the WaypointProgressTracker.
Now this progress tracker you'll see also requires a circuit of waypoints and you can give it the
circuit that we created just before.
The other thing it also has down the bottom is a Target.
The Target is going to be an object that is a child of the tank.
So select the tank, right-click
(this is in the Hierarchy) 3D Object > Cube.
Grab that cube and move it away from the tank a little bit - you can see it there.
The Cube is going to become a goal for our tank to travel towards
and the cube will stick to the circuit and be pushed around the circuit
by the WaypointProgressTracker code and the tank is going to follow it.
So the cube itself doesn't even need to be visible and later, when you put this into production,
you wouldn't have it visible.
First of all, just turn off your box collider because you don't need any strange physics occurring
in this system.
Now select the parent tank and drag-and-drop your little cube into the target.
Right, at this point, let's press Play and see what happens.
All right.
So you can see that you've got the cube and it's being moved. It's sitting on the circuit.
There's this green line going between the tank and the cube
and there's also this ball here as well on the circuit.
Now all these values are controlled in the WaypointProgressTracker script that's attached to the tank.
Basically, what they're doing is creating a little rubber band between our cube and our tank, such that
the cube can't get too far away from the tank whilst it's staying on the circuit.
If I move my tank closer to the cube
and start to come up behind it,
you'll see that the cube makes its way along the circuit.
So that's the progress tracker
moving the cube for us, automatically.
Now you don't want to play your game by dragging the tank around in the Scene view!
So we want to program it to automatically follow the cube and we've already created this code, so if you
remember when we had the zombie following the driveable cube around and we created a script called
MoveLocal?
It's that exact same script that we now need to put on the tank and tell it that our goal is going to
be the cube.
So I've created this script in a file called FollowGoal.
Besides the name change to FollowGoal, there's really only one other line of code that has been modified.
We still have our 'public goal' that we're going to pass through here and now instead of it being a driveable cube,
it's going to be that cube that is being driven by the circuit.
We still have our speed, accuracy and our rotation, as we had before.
In fact, we're not even using accuracy in this case so you could take that out. In the LateUpdate
is where all the work happens, so we still want to do a lookAtGoal.
Then we set our direction,as before. We slerp-rotate towards that direction and then we push our character
forward.
Notice that the accuracy 'if' check has now gone because we don't want our tank to stop when it gets close
to that cube because if it stops, the cube stops and you don't want that, you just want the cube to keep
moving around the circuit and the tank to keep following.
So save that and go back into Unity, select the tank, grab hold of that new FollowGoal code, drag-and-drop
it onto the tank in the Inspector, so that you'll have the WaypointProgressTracker and you'll
also have your FollowGoal.
For the exposed Goal variable, you want to add your cube object, so drag-and-drop that down into the 'Goal'.
Now when you press Play and you'll see I've already aligned my cube ready to go to point 1 and my tank
just behind it.
Of course you can have these anywhere.
Let's press play
and now the cube will start calculating its trajectory along the circuit
and you can see that the tank is moving.
The other thing you'll find is because of the way this tank is following the cube with the speed and
the rotation, is that the tank can cut corners...because the tank is trying to go straight towards the
cube.
It really has no knowledge and doesn't care about your waypoints.
So the cube is acting as a little guide.
Now if you want to modify how far ahead that cube can get and how fast it goes around the corners, then
you can change in the WaypointProgressTracker
how far it will 'look ahead' and how far it's speed for 'look ahead' will be as well.
You can also modify a point-to-point threshold and this threshold is how close we want the cube itself
to get to each of these before it's considered having visited them
and that's essentially our accuracy.
And so that's the waypoint script that comes with Unity.
Feel free to use it both together (the circuit and the tracker) or use one of them with your code,
whatever you like.
They're all doing the same thing. Our code is really quite simple because we're just pushing an A.I. forward
around the circuit
and so you might prefer to use that because you've written it and you can modify it to your own understanding.