This lecture extends on the last lecture by now moving our characters towards a goal, where they will
then stop. To do this, you'll need a goal location.
I've created a simple cube by right-clicking, 3D Object > Cube and then positioning it somewhere in
the environment.
We're going to get one of the characters to move towards the goal, to begin with.
So select the characters that are in the scene and make sure that you remove the script that's already
attached to them.
We're now going to create a new C# file called MoveToGoal.
It's a little bit different to the Move code that we wrote before,
but we still need to calculate with vectors and at the top begin by adding in a float for speed and
I've got that set to 1.0.
In fact, I might just set that up to 2 so that things go a little bit faster this time.
Then I have a public exposed transform called
'goal' which is now changing from the previous code. Before, we had goal as a vector.
Now it's a position in the environment. Inside of our LateUpdate, we need to calculate direction.
This is the vector between the goal position and the character's position. To do that,
we simply minus where we're going
(so the position of the goal) minus where we currently are.
So this is 'where we're going' and this is 'where we are'.
It has to be in that order.
If you switch them around the other way, your vector will be facing in the opposite direction
and your character will go along the same vector...
or at least along the same kind of line towards your target,
but it will be traveling in the opposite direction.
If you ever get that happen, then you know that you've got these two things around the wrong way.
Once you've calculated the new vector to travel along, you then again use your Translate and you
put your vector you calculated inside,
multiply by speed and multiply by Time.deltaTime.
So we're still traveling along a vector
but this time we've calculated it.
So save that, switch back into Unity.
Now you'll want to grab one of your characters and drag-and-drop that script from the project onto them.
Here you can see I've got the MoveToGoal script attached and I have set the speed to 2 (well, the code
did anyway).
Grab hold of your cube and make sure you drag-and-drop that in as the goal position.
Now press Play and have a look what happens.
So your character has calculated the direction it needs to go and it will get to the goal location and then
it kind of stops moving
but it's jittering. The reason why is because you're still inside that update loop asking it to
calculate the direction to the goal and move towards it.
Now in most cases, you're not going to get your character spot on the exact location of your goal and
therefore you need to have some kind of 'near enough is good enough' calculation included.
Just before we do that, I want to show you something.
If we move our character over here now and press Play, it will calculate a new vector to the goal and
move towards the goal.
Now to stop that jittering that happens when they get to the goal, go back into the code
and we want to put something in the update here to test if we've reached our goal.
If we have reached our goal, then we don't want to keep calculating the vector towards it and moving
towards it.
So you can do that by testing the length of the direction. You've already calculated this vector
and can you remember what it's called, the length of a vector? It's the Magnitude.
So we can say 'if(direction.magnitude > 5) then move
towards the goal.
So save that and let's go and check it out.
So every time it loops and direction gets calculated, it gets shorter and shorter,
the vector itself. It doesn't stay set to the original vector. Even though it's still in the same direction,
it will be shorter.
So now you can see that it moved.
but not very far and that's because a distance of 5 is about that distance
in this case, because these are quite small little characters and you'll have to take it upon yourself
to check the scaling that's going on within your world.
So let's go back here and let's make this 1 and run it again.
Ok,
so that must be a distance of 1 from the cube and if we click on the cube and have a look at the one
I created, you can see that the scale is 0.2.
So that makes that cube (in world terms)
about 20cm across. When a cube is at size 1 which is its default size, that would be
1m x 1m x 1m in the Unity world
and therefore you can imagine that 5 of those cubes would fit across that space there, for that distance
of 5 from before.
Now you can see that one is still quite large, if you want your character to be right on top of the goal
location.
So let's just try once more with a smaller value. Go back into MoveToGoal and we'll change this to
0.2f.
Save that and run it again
and the character should be very close to the target
in this case and you can see that he is, so that's pretty acceptable.
I'm going to move this value of 0.1 up the top, so let's make this 'public float accuracy'
because it is the accuracy that we're willing to take as far as being close to a goal. Let's set it
to 0.01f.
So we're going to make it very close
and then down in here, we'll put accuracy...like that.
All right, so save that and we'll switch back and run it and just see if that makes any difference with
that very tight accuracy.
That's pretty good.
What I want to show you is something that will cause your character to still jitter with this particular
code.
Let's change the speed to five with that really tight accuracy and let's run it again
Ok,
so the character jittered before it eventually got within that accuracy.
What's going on here is that it got to the goal, it overshot the mark, it recalculates the direction
back towards the goal, overshoots the mark and ends up bouncing around like this because your 5 speed
here is pushing it over the goal and then pushing it back over the goal and pushing it over the goal
like that as well.
In this case we were lucky where it did eventually move to a position that it could get within that
accuracy
but sometimes you won't get in with that accuracy and you'll get some really strange behavior going
on as far as the character dancing around the goal spot.
That's because it never ever is getting there within your accuracy.
So if you get that, just play around with your accuracy values until you've lifted them up high enough
to stop that from happening, otherwise you're going to have to reduce the speed at which they are attacking
your goal position from.
I'm going to put this accuracy back up to 1 for this one
and then the other character...
let's put the same code onto it and leave it with the default speed,
but let's set the accuracy to 0.1 instead of 1.
We also need to set the cube into the goal location for this guy here
and now if you press Play, they'll move towards the goal position. As we've currently got it working,
they will slide along from their current position to the goal position but they don't turn and face
the direction that they're traveling in
and that would be a nice addition for a character to do that.
In the olden days, we had to calculate the angles between vectors and which
side the vectors were on, relative to the other vectors, in order to figure out how to turn your character
around.
Now we've got this great function called LookAt that Unity has
which does all that hard work for us and I'm going to put it in the Start function so that our character
first turns and looks at where it's about to go.
That method, or function is called LookAt and you add it to the end of the transform and then give
it the goal position that you want your character to look at and it will snap around and look in that
direction.
Now at this point, if I run it, because we've changed the orientation of the character this Translate
is not going to work properly and we'll just save this and go back and have a quick look at what you
get and I'll show you how to fix it.
So there we get this and you can see that the characters tend to arc towards it
and this character is going to just spiral around until it gets close enough.
What's happening there is that now that these characters are no longer (0,0,0) rotation up here in the
transform.
If you've been following along and you've changed the rotation of your characters, you probably couldn't
figure out what was going wrong with your code
and this is the exact problem.
So in your MoveToGoal, what you want to do in your Translate is 'translate' your character
along this vector in 'world space' as opposed to 'local space'.
Now if you save that and run, you'll see that your characters turn towards their goal and then they travel
towards it. Over in the Scene, I've got these red lines that you would have seen and that's drawing
in the vectors from the code with a Debug.DrawRay
which draws a ray from the position in a particular direction and then you give it a color.
This is really useful for debugging to see what's going on.
So I've just included that, so that you can use it in your own code to see which vectors are doing what
and which way they're pointing.
All right so that's the easy way to do a LookAt.
You might have noticed at this point, if we run it again and you grab hold of the cube and in the scene
you move it around, you will get the characters responding to its location just naturally, because of
what's in that update.
Notice though the LookAt isn't updating and that's because it's still in the Start function.
So if we change that LookAt here and make sure that we recalculate it every time within our Update,
the characters will always be looking at that cube and then what you could do is get some driving script
so that you can drive that cube around with the arrow keys and the characters would move wherever it goes.