In this lecture, we will continue working on our crowd simulation.
Since the last lecture, I've added some extra scenery into the scene that you'll find in the Street folder
in the project under Prefabs.
I've also added another goal location so the crowd walks along two sides of the buildings.
Now we make some modifications to their animation controls to stop them walking like a regimented Army
before we add a dynamic obstacle.
First thing that we need to do is to stop them walking in step with each other.
Remember, they are playing exactly the same animation at exactly the same speed.
What we can do to make that look a little different is to, first of all, make it so that they're not in step
with each other, so that they are at different phases through that walking loop and the other thing we
can do is to change how fast or how slow they're walking.
So the first thing we want to do is find our animation.
Let's click on Assets > People and then there's the 'Crowd'.
Double-click on that and this is the Animation Controller
with our 'Walking' in it.
If you select the Walking animation and look in the Inspector, you'll see that there is a
Speed (that we'll come back to in a moment) and a 'Cycle Offset'. This Cycle Offset is a value between 0 and 1
which specifies where in the cycle the animation is playing.
Now if you set that to random values for all the characters, they will become out of step with each other.
To do that easily, we need a parameter that we can grab from our code.
So, first of all, we go over to the Parameters section and then click on '+'.
We're going to add a Float and we will call that float wOffset and that's because it's a walking
offset.
Then for our walking animation, select that and go over to the Inspector.
You want to tick the Parameter box
that's right
next to Cycle Offset and it will automatically fill in wOffset as the parameter.
Now whatever value we give wOffset in our code will come through here and set the offset for the walking.
To set that offset, go back to your AIControl code. In the Start, just after we've set up the animator,
before we start the walking animation, we will set the offset value for it, so that it's going to be a
random value between 0 and 1, going into this wOffset.
It's a SetFloat
in this case, because it's a float value.
So save that, switch back to Unity and press Play
and we should now see that our characters won't be walking in-sync with each other, which makes it look
a little bit more naturalistic.
Now we can also do the same thing with the speed. If we go back to our Walking in the animator, you'll
find in the Inspector that there is the Speed value
we looked at before.
It also can be changed with a parameter and it has a multiplier underneath, that you can see here.
Let's create that first of all. So we go over and create a Float and let's call this 'speedMult'.
Initially it will be set to 1,
otherwise you won't be going anywhere because if you multiply by 0 then it will be going at a speed
of 0
and then select your Walking animation, click the Parameter box next to it and then change its multiplier
to speedMult.
Now we can modify speedMult also in our script.
So if we open up our script again (the AIControl) and we can do that up in the Start, so we can give them a random
walking speed.
So let's go
anim.SetFloat("speedMult"
and then Random.Range, let's say somewhere between 0.5 and 2. Let's put an 'f' on there for our
float
and save that. At this point, you're going to get only the speed being multiplied in the animation.
So it will either slow down or speed up
but the agent's speed (the Nav Mesh Agent) isn't being changed and therefore you want to make sure that
if you change the animation speed, that you also change the speed at which the Nav Mesh Agent is moving as well.
First, we need to save what your multiplier is for your speed, so let's put
'float sm =' and we'll take this out of here.
Copy that.
Paste it up there
and then put this as our 'sm' and then we'll also use the 'sm' on our agent speed, so
'agent.speed *= sm;' like that.
Now we have our speed multiplier applied to our animation AND the agent movement.
OK so save that and we'll go back into Unity and we'll play it and we should get different speeds
as you can see there
and the animations are different as well.
So multiplying it by 2 as the maximum, they do walk quite fast but you can
see that the animation is keeping up with them.
If you want to slow those down because it doesn't look particularly naturalistic, you could have
people going along at a leisurely 0.1f pace and then maybe people at say 1.5f.
It's up to you
what you have in there
and the effect that you're actually after, but at least everyone now isn't walking in step with each other
and some people are taking a casual stroll and other people are in a hurry.
Now we're going to add a dynamic obstacle onto the NavMesh for our agents to move around and that obstacle
can be anything, but we're going to make it a first-person controller.
So go into your Assets and import the Character package,
then once you've done that you'll get a FirstPersonCharacter package down in 'Standard Assets > Characters'
of your Assets folder.
Go into Prefabs and grab hold of the FPSController and drag-and-drop that into the Scene.
If it's below the surface, just lift it up a little bit and I'm just going to move it back because I'm
going to want to walk it into these people going up this way, so we can see it. Now,
it has a camera on it which we will use in a moment but for now, we'll use the current camera that's pointing
at the scene because I want to walk this around and for you to see that these agents are going to completely
ignore it at first.
So with that there, press Play and then you can use the W, A, S & D keys to move your character around and
you'll notice that you can go straight through people and they don't even care or know that you're
there.
So if you were playing this in first person mode, the same thing would happen...people would just walk straight
up and then straight through you.
Ok, so just press Escape to get your mouse control back and stop playing. To make this first person controller
into an obstacle on the NavMesh,
we add a component to it called a 'Nav Mesh Obstacle'.
So select the first person controller in the scene and go over to the Inspector, add component and we're
looking for a Nav Mesh Obstacle.
Click on that.
Now you don't have to make this object static, like we have with all the other geometry because it's
not static. It's going to be moving around and the agents are going to react to it. Now
within the Nav Mesh Obstacle, you can also set whether it's going to be a Capsule or a Box.
Our character is a capsule, so we'll put a capsule on there.
At this point you'll see that there's 2 capsules sitting over there. One is the physics collider and
one is your NavMesh collider and you can adjust them to be exactly the same. I'll leave them like they are
because they're pretty similar.
So now when we press Play and we take our character for a walk, we'll find that people avoid it and so
they're going around and if we bump into people, we will also affect where they are.
So to get a view of what this looks like, hit Escape and stop playing. Let's go
down, find our camera that we've got from before and you can delete it or just turn it off.
Now when we press play, it'll default over to the first person camera and we can now walk through people
and they will avoid us. So you can see this character going around
and we also affect those around us as well.
You can push them out of the way
and as I said before, you can add this Nav Mesh Obstacle to any game object in your scene to make it
a dynamic obstacle on the NavMesh, so you could also have a car that you're driving along and have IT
as a Nav Mesh Obstacle, so that any agents that are stuck on there will have to navigate around that
moving object.
Of course, as you can imagine, the more of these obstacles that you add that are dynamic, the more the
NavMesh code has to work to keep recalculating the paths.
So when you can have something that's static and doesn't move, you want to make it static and think about
what's going to move and make it a non-static and add the Nav Mesh Obstacle to it.