Adding falling and landing animations to the Locomotion System

I would appreciate a little help adding a falling and landing animation to the JumpAndIdle script. I have added two public variables for the additional animations and I am modifying the sections commented “If character has landed” and “If character is falling”. I have also changed some of the wrapmodes for the other animations and the scene I am using is the demo Crate Climb Scene.

I am trying to crossfade to the landing animation after the jump and falling states. At the moment it crossfades after a jump, but also whenever the character is grounded and not moving, which looks quite bad.

For the falling state I have a looping falling animation which I would like to crossfade to after the character has fallen for a certain period of time. For some reason it is never triggered, and only the jump animation plays the entire way down. Do the “Jump Time Start” and “Fall Time Threshold” parameters have something to do with this? I have both set to zero since I am not exactly sure what their function is. I cannot find any documentation or information detailing the function of these parameters either.

Here is my JumpAndIdle script:


using UnityEngine;
using System.Collections;

[RequireComponent(typeof(AlignmentTracker))]
public class JumpAndIdle : MonoBehaviour {
	
	public AnimationClip jumpingAnimation;
	public AnimationClip landingAnimation;
	public AnimationClip fallingAnimation;
	public float jumpTimeStart = 0.0f;
	public float fallTimeThreshold = 0.2f;
	public AnimationClip waitingAnimation;
	
	private bool doJumping = false;
	private bool doWaiting = false;
	
	//private LegAnimator legA;
	private AlignmentTracker align;
	private CharacterMotor cm;
	
	private bool grounded;
	private bool waiting = false;
	private float idleTimer = 0.0f;
	private float fallingTimer = 0.0f;
	
	// Use this for initialization
	void Start () {
		//legA = GetComponent(typeof(LegAnimator)) as LegAnimator;
		align = GetComponent(typeof(AlignmentTracker)) as AlignmentTracker;
		cm = GetComponent(typeof(CharacterMotor)) as CharacterMotor;
		grounded = false;
		
		// Only use jumping if the jumping animation has ben set
		if (jumpingAnimation!=null) {
			animation[jumpingAnimation.name].wrapMode = WrapMode.Once;
			doJumping = true;
		}
		
		// Only use idle animation if it has been set
		if (waitingAnimation!=null) {
			animation[waitingAnimation.name].wrapMode = WrapMode.ClampForever;
			doWaiting = true;
		}
		
		// Start with locomotion
		//animation.Play("locomotion");
	}
	
	void OnEnable () {
		if (animation["locomotion"]!=null) animation["locomotion"].weight = 1;
	}
	
	// Update is called once per frame
	void Update () {
		float speed = align.velocity.magnitude;
		
		// CrossFade quick to jumping animation while not grounded
		if (doJumping) {
			// If the jump button has been pressed
			if (cm.jumping) {
				grounded = false;
				waiting = false;
				// Fade to jumping animation quickly
				animation.CrossFade(jumpingAnimation.name, 0.1f);
				animation[jumpingAnimation.name].time = jumpTimeStart;
				animation[jumpingAnimation.name].wrapMode = WrapMode.Once;
			}
			// If the character has walked over a ledge and is now in air
			else if (grounded && !cm.grounded) {
				grounded = false;
				waiting = false;
			}
			// If the character has landed on the ground again
			else if (!grounded && cm.grounded) {
				grounded = true;
				waiting = false;
				fallingTimer = 0;
				animation.CrossFade(landingAnimation.name, 0.1f);
				// Fade to locomotion motion group quickly
				animation.CrossFadeQueued("locomotion", 0.1f);
			
			}
			// If the character is falling
			else if (!grounded && fallingTimer<fallTimeThreshold) {
				fallingTimer += Time.deltaTime;
				if (fallingTimer>=fallTimeThreshold) {
					// Fade to jumping motion group slowly
					animation.CrossFade(fallingAnimation.name, 0.2f);
					animation[fallingAnimation.name].time = jumpTimeStart;
					animation[fallingAnimation.name].wrapMode = WrapMode.Loop;
				}
			}
		}
		
		// CrossFade to waiting animation when inactive for a little while
		if (doWaiting) {
			if (speed==0) {
				idleTimer += Time.deltaTime;
				if (idleTimer>3) {
					// if the idle animation is not in the middle of playing
					if (
						animation[waitingAnimation.name].time==0
						|| animation[waitingAnimation.name].time>=animation[waitingAnimation.name].length
					) {
						// Then rewind and play it
						animation[waitingAnimation.name].time = 0;
						animation.CrossFade(waitingAnimation.name);
						animation[waitingAnimation.name].wrapMode = WrapMode.ClampForever;
						waiting = true;
					}
					// Don't play again for a little random while
					idleTimer = -(2+4*Random.value);
				}
			}
			// If we have started to move again
			else if (speed>0 && waiting ) {
				// Crossfade to locomotion
				animation.CrossFade("locomotion");
				waiting = false;
				idleTimer = 0;
			}
		}
	}
	
}

Would appreciate any help with what I am doing wrong, I’m sure it is something simple but I can’t see it at the moment.

Have another look at the bootcamp soldier and see how it is handling the same situation. I’m pretty sure that when you simulate bootcamp the soldier stands perfectly straight and doesn’t do a landing crouch unless he jumps first. One way you could do it is check which animation has played before triggering a land boolean. If the jump animation has played go to a land animation, else go to a grounded animation. Use Animation.IsPlaying for that.