The next stage in creating the player is
to make a script to control his movement.
Select the player and add a new script
to him called Player Movement.
Empty the script.
Let us start out as usual with the
public variables. We need an audio clip
to store the sound of the player shouting.
We will call the variable shoutingClip.
We are going to use a Lerp function
for changing the direction of the player.
As such we will need a smoothing value.
When we set the speed parameter of the player's
animator we want to apply damping.
We will store the damping time as a public float.
We will also need a couple of private variables
to store references. Firstly to the
animator component
and secondly a reference to the hash IDs script.
Now we can use the awake function to
allocate these references.
We are also going to use the awake function
to set the weight of the shouting
layer in our animator controller.
The weight of a layer is it's effectiveness
so if set to a value of 1 this layer's
animations have the potential to completely
override any layers beneath it,
such as the base layer.
Since we are using an avatar mask
and most of the time the Shouting layer
will be in an empty state we can
set the layer weight of this to 1 with
out it effecting the base layer's animation.
This function takes 2 arguments.
The first is an integer, an index of the layer,
for example the base layer is 0,
and the Shouting layer is 1.
And the second argument is that it's
effectiveness. A value of 1 as we stated earlier.
The player is a physics object,
so we will be dealing with his movement
in the fixed update function. Add this now.
We are going to start by cashing the inputs
that we get from the use.
This way we can use them when we need them
without having to call any input
functions again.
Now that we have our input, let us make a
function to use that information to
manage the movement. We will call it
MovementManagement, and it needs to
take in parameters of the input variables
that we have just cached.
First thing we can do here is set the
Sneaking animator parameter by using the
sneaking variable that we are taking as
an argument in this function.
We can use a reference to the Hash IDs script
to determine the parameter we are setting.
The style of movement we are going to have
for the player is one in which the player's
direction is determined by the axis input.
The player turns to that direction and
runs forward. We are going to have the
rotation of the player changing smoothly
but quickly in order to give the controls
a responsive feel.
To achieve this first we need to determine
if there is any directional input.
To make the player rotate to the direction
defined by the directional inputs
we will make a function to handle it.
This function will need the horizontal
and vertical variables in order to
determine a target rotation.
If we imagine the new direction we want
the player to face as a vector
it can be represented by an amount in the
X direction of the horizontal input
and an amount in the Z direction
of the vertical input.
So if both horizontal and vertical are 1,
that is if up and right are being pressed
then the player should head in the positive
X and Z directions.
We will store this intended direction
as a vector3.
Now we need to convert this vector to a
quaternion so that we can adjust the
player's rotation towards this.
A quaternion is a way of storing a rotation.
This is a more advanced topic but we need this
to assign rotation back to our character.
Unity has a built-in function that
simplifies this process for us, called
LookRotation.
LookRotation is a static function of the
quaternion class. It takes two arguments.
Firstly the vector representing the direction
you want to convert to a quaternion
and secondly a vector representing
the up direction.
We want to smooth the rotation of the player
as he turns. To do so we are going to use
Lerp to get a new rotation that is a slight
change from the current rotation
in the direction of the target rotation.
We will use our current rigidbody.rotation
as the direction to go from
and the target rotation from our
key input as the direction to lerp
towards, with our turn smoothing variable
to control how long this takes over time.
We can then set the rigidbody's rotation
to this new rotation using
rigidbody.MoveRotation.
With the rotating function finished
we can return to the movement management function
to put a call to it.
Whilst we are still within this If statement
we know that we are receiving input
so we know the player should be moving.
As such we can set the speed parameter
of the animator. We are going to set it to
5.5 as this is approximately the speed of the
animation as determined by the blend tree.
We are going to apply damping to the parameter
as we set it. This will ensure
transitions are smooth whilst
remaining responsive.
If however we are not receiving any input
then we want to set the speed to 0.
With the movement management function finished
we can put a call to it in our fixed update function.
We have still to add the audio for our player,
both his footsteps and the sound of him shouting.
For this we will make an audio management function.
We only want the footsteps audio clip to
play whilst in the Locomotion state.
So we should first of all check if that's
the state that the player is currently in.
We can use the Name hash, since we have the
appropriate state stored in our HashIDs script.
Here we are using GetCurrentAnimatorStateInfo
with a value of 0 to refer to the state
that we are in in the base layer.
We also only want to play if the
clip is not already playing.
However when we are no longer in the
Locomotion state we do not want the
clip to continue on until it is finished
so we will stop it here.
Because we are using our audio source component
to manage the footsteps of the player
we will be using the PlayClipAtPoint function
to manage the shouting. This is because the
audio source will already be playing back
the footsteps and we do not want replace it
with the shouting. The condition for playing
back the shouting clip is that Shout is true.
PlayClipAtPoint takes 2 arguments,
an audio clip and a vector3 for position.
It creates a new object in the world at
the specified position and plays a
sound there. This object then self-destructs
so that it is no longer left in the scene.
Now our audio management function is complete.
In order to call this function however
we need to place it in the update function.
We will place this in our script below
the fixed update function. We do not need
to put update here but it makes the flow
of the script slightly easier to understand
when reading it. The update function could
be anywhere, it is purely a matter of preference.
The first thing we want to do is cache
the input of the Attract button.
Next we are going to parse this input
as a parameter to the animator controller
so that the player performs the correct animation.
Finally we will parse the Shout Bool
in to the audio management function
as we call it so that this is the
triggering input that causes our shout to play.
Now we can save the script and return to the editor.
The player is now ready to test.
But before we do let us tidy up our script
folder one more time. We are going to
add a new subfolder to the Scripts folder
called Player. Select the Scripts folder
in the project panel and go to
Create - Folder.
Call this Player. Select the assets folder
and then drag in PlayerMovement in to
this Player folder.
Do not forget to save the scene and the project now.
Then we are ready to test the player.
Let us zoom out a little from him in the
scene view and rotate our view around
to mimic the position of the camera that
we will place in later.
Before we test we will need to assign the
Shouting audio clip to our PlayerMovement script.
So select the player character char_ethan
again in the hierarchy.
You will see that the PlayerMovement script
has None Audio Clip next to Shouting clip.
So in the audio folder drag
PlayerAttractAttention
to this variable.
Now let us play test. Press play at the top
of the interface.
You should now be able to drive your character
around observing him in the scene panel.
You can use the arrow keys or W A S and D
on the keyboard.
Remember you can use left shift to sneak
and you can press X to shout.
As we are play testing we notice that the
sneaking animation seems rather slow.
But we can adjust this very easily.
Press the play button to stop testing
and return to the animator window.
Go to the base layer and select the Sneak state.
In the inspector set the speed
to something greater, let us try 1.7.
Now let us press play again and see the change.
Now if we move and hold shift
our sneaking is a little faster.
These are the kind of tweaks that you can
make as you test your game to improve
it over time.
In the next assignment we will make a script
to handle the player's health.