How would I make a script that manages the animations that need to be played when im pressing some buttons, for example:
If press Shift - then play Sprint animation
if Press Ctrl - then play Crouch animation
How would I make a script that manages the animations that need to be played when im pressing some buttons, for example:
If press Shift - then play Sprint animation
if Press Ctrl - then play Crouch animation
What you are asking for is alot, and it is two things : manage the user inputs to determine the action ; run animations based on the current action ;
I am going to write a character controller and animator for this Base Male Model (Muscular / Lean) by dogzerx2 : http://forum.unity3d.com/threads/131238-Base-Male-Model-(Muscular-Lean)
Start a new project. Import the model from the asset store. Create a new javascript and call it PlayerAnimator . Open the script to edit.
The animated character has a lot of different animations to control. Make a list of all the animation states. Be sure the spelling is correct, this will become a handy reference later for the animation names :
// tPose
// idle
// run
// sprint
// walk
// strafeLeft
// strafeRight
// crouch
// crouchWalk
// crouchRun
// crouchStrafeLeft
// crouchStrafeRight
// jump
From that information, make an enum and a variable to store the current state.
enum animationState
{
Idle, Running, Sprinting, Walking, StrafeLeft, StrafeRight, Crouching, CrouchWalk, CrouchRun, CrouchStrafeLeft, CrouchStrafeRight, Jumping
}
var myState : animationState;
At the start and by default the Idle animation is usually looping.
function Start()
{
animation.Play( "idle" );
myState = animationState.Idle;
}
for each animation (and therefore each animation state) you are going to need a function to 1/ check if that animation is already playing 2/ if not then CrossFade to that animation.
Set up a function for each enum state, start with AnimateTo , for example :
function AnimateToIdle()
{
//
}
When an animation is required, a function for that animation can be called. Now to add the conditions.
function AnimateToIdle()
{
if ( myState != animationState.Idle )
{
animation.CrossFade( "idle" );
myState = animationState.Idle;
}
}
function AnimateToRunning()
{
if ( myState != animationState.Running )
{
animation.CrossFade( "run" );
myState = animationState.Running;
}
}
… and then the same for every other function, changing each enum value and animation name.
Now to the BaseMale folder, open the folder Scenes and double-click on scene. leave the following items and delete everything else :
// backLight
// baseMale
// camera
// mainLight
// platform
Remove the script component from the camera called cameraViewObject .
Attach the PlayerAnimator script to the baseMale in the scene. Now if the scene is played, the model should go from tPose to idle.
Save this scene as Test_0 or whatever you like to call it.
Now to write something that takes inputs, determines an action based on those inputs, and calls the correct animation.
Create a new script and name it PlayerController . Just like the animator, it is going to use an enum and then a variable to remember what state is derived from the inputs.
Write a list of all the possible movements.
// - Movement States -
// - for walking
// idle
// walk forward
// walk backward
// strafeLeft
// strafeRight
// walk forward diagonally
// walk backward diagonally
// - for crouching
// crouch
// crouchWalk forward
// crouchWalk backward
// walk forward diagonally
// walk backward diagonally
// - for sprinting
// sprint
// sprint forward diagonally
// crouchRun
// crouchRun diagonally
// - for jumping
// jump
Now to write an enum to include all the possible movements
enum movementState
{
Idle, Crouching, Jumping,
CrouchWalkingForward, CrouchWalkingForwardLeft, CrouchWalkingForwardRight, CrouchStrafeLeft, CrouchStrafeRight, CrouchWalkingBackward, CrouchWalkingBackwardLeft, CrouchWalkingBackwardRight,
WalkingForward, WalkingForwardLeft, WalkingForwardRight, StrafeLeft, StrafeRight, WalkingBackward, WalkingBackwardLeft, WalkingBackwardRight,
CrouchRunForward, CrouchRunForwardLeft, CrouchRunForwardRight,
SprintingForward, SprintingForwardLeft, SprintingForwardRight,
WalkingJumpingForward, WalkingJumpingForwardLeft, WalkingJumpingForwardRight,
SprintingJumpingForward, SprintingJumpingForwardLeft, SprintingJumpingForwardRight
}
var myState : movementState;
Alot of different states : 3 for each standing still state, 8 for each direction crouched and walking, 3 for each crouch running and normal running forward, 3 for each walking and running jump. Now set up some variables for the inputs to calculate the exact state.
var inputVector : Vector3 = Vector3.zero;
var inputDeadZone : float = 0.1;
var isCrouched : boolean = false;
var isSprinting : boolean = false;
var isJumping : boolean = false;
Then create a function called GetPlayerInput to get and store all the player inputs to use in calculations. Call this function from Update.
function GetPlayerInput()
{
// reset inputVector
inputVector = Vector3.zero;
// get player Vertical input
if ( Input.GetAxis("Vertical") > inputDeadZone || Input.GetAxis("Vertical") < -inputDeadZone )
{
inputVector += Vector3( 0, 0, Input.GetAxis("Vertical") );
}
// get player Horizontal input
if ( Input.GetAxis("Horizontal") > inputDeadZone || Input.GetAxis("Horizontal") < -inputDeadZone )
{
inputVector += Vector3( Input.GetAxis("Horizontal"), 0, 0 );
}
// get player Crouch input
if ( Input.GetKeyDown(KeyCode.LeftControl) )
{
if ( isCrouched )
{
isCrouched = false;
}
else
{
isCrouched = true;
}
}
// get player Sprint input
if ( Input.GetKeyDown(KeyCode.LeftShift) )
{
if ( isSprinting )
{
isSprinting = false;
}
else
{
isSprinting = true;
}
}
// get player Jump input
if ( Input.GetKeyDown(KeyCode.Space) )
{
isJumping = true;
}
}
At this point it would be ok to attach the script to the baseMale in the scene. If it is run, the Inpector variables can bee seen changing for the inputVector and sprint/crouch booleans.
From this all the states should be able to be calculated. The next function may seem long and messy, but it is just logically stepping out what is happening from the inputs.
// if the input is forward
// is it to the left, right or straight
// if the input is backward
// is it to the left, right or straight
// is the input is changed by being crouched or sprinting
I have also split the functions up depending on if sprinting or crouching is activated, so my walking function is :
function DetermineStateWalking()
{
if ( inputVector.z > 0 ) // forward
{
if ( inputVector.x < 0 ) // left
{
myState = movementState.WalkingForwardLeft;
}
else if ( inputVector.x > 0 ) // right
{
myState = movementState.WalkingForwardRight;
}
else
{
myState = movementState.WalkingForward;
}
}
else if ( inputVector.z < 0 ) // backward
{
if ( inputVector.x < 0 ) // left
{
myState = movementState.WalkingBackwardLeft;
}
else if ( inputVector.x > 0 ) // right
{
myState = movementState.WalkingBackwardRight;
}
else
{
myState = movementState.WalkingBackward;
}
}
else if ( inputVector.x < 0 ) // left
{
myState = movementState.StrafeLeft;
}
else if ( inputVector.x > 0 ) // right
{
myState = movementState.StrafeRight;
}
else
{
myState = movementState.Idle;
}
}
Each function varies based on what inputs are given and what movements are allowed for that input. For example, if the character is running then goes backwards, there is no running backwards so running is toggled off and a state of walking backwards is chosen.
So finally all this information has been gathered and a state has been determined, now to send this information to the animator script and make it work. The script needs to find and store a reference to the PlayerAnimator script so it can be communicated with.
var plyrAnimator : PlayerAnimator;
function Start()
{
plyrAnimator = GetComponent( PlayerAnimator );
}
Then a very long switch-case needs to be written, with a case for every possible state, 31 using my example. But once this is written, it becomes a very powerful tool for other things like assigning the relative movement speed ( if you are walking backwards, set the move speed to something lower than a walking forward speed, same for run crouch etc).
function ApplyState()
{
switch( myState )
{
case movementState.Idle :
plyrAnimator.AnimateToIdle();
break;
case movementState.Crouching :
plyrAnimator.AnimateToCrouching();
break;
case movementState.Jumping :
plyrAnimator.AnimateToJumping();
break;
case movementState.CrouchWalkingForward :
plyrAnimator.AnimateToCrouchWalk();
break;
case // .... etc etc for all 31 states
And that’s it. One controller and animator. Usually a project like this would also have a separate PlayerMotor script and Camera script.
Here is a webbuild using the above instructions : http://www.alucardj.net16.net/unityanswers/AnimatorExample1.html
Here is the full PlayerAnimator script : http://www.alucardj.net16.net/unityanswers/PlayerAnimator.js
Here is the full PlayerController script : http://www.alucardj.net16.net/unityanswers/PlayerController.js