title: Unity3D Third Person Controller and Animations
body: <p>My problem is that a custom walk animation I have set in the third person controller of Unity3D is not shown.  </p>
  
  <p>The animation is imported from a FBX file with the model@walk.fbx structure. I know the animation works, because if I use it as the idle animation it shows. On the other hand, it also doesn't seem to be an issue with the controller script, as it works fine with the prototype character.</p>
  
  <p>It seems that the animation being played is the one selected in the Animation component (which has 'Play Automatically' selected). Any attempts to change the animation from the third person controller work for the prototype character, but not for mine.</p>
  
  <p>I don't have nor want run and jump animations. With the prototype character I set the walk animation on each of those with no adverse effects. The controller doesn't turn off animation this way, seeing that there are no log entries in the console from the third person controller script. The relevant line with the CrossFade call is getting called.</p>
  
  <p>Any clues as to where I could look next? Is it more likely an issue with the controller, or with the animation? Something else completely?</p>
  
  <p><strong>Update:</strong> Below is the code of my controller. It works fine when I use the sample model of the construction worker that is provided with Unity. The lines with <code>_animation.CrossFade</code> are getting called at the expected times. Using <code>Play</code> or <code>Blend</code> instead doesn't help. There are no errors logged in the console.</p>
  
  <p>For our custom animations however it doesn't work. I am now suspecting the issues lies with the model. Unfortunately I am not at liberty to share a sample of that model. I've asked the animator for further details on how he created the FBX export. Are there any specific settings he needs to use for the model to work in Unity? It remains odd though that the animations do work if I add them indepently to the scene.</p>
  
  <pre><code>// Require a character controller to be attached to the same game object
  @script RequireComponent(CharacterController)
  
  public var idleAnimation : AnimationClip;
  public var walkAnimation : AnimationClip;
  
  public var walkMaxAnimationSpeed : float = 0.75;
  
  private var _animation : Animation;
  
  enum CharacterState {
      Idle = 0,
      Walking = 1,
  }
  
  private var _characterState : CharacterState;
  
  // The speed when walking
  var walkSpeed = 2.0;
  var speedSmoothing = 10.0;
  var rotateSpeed = 500.0;
  
  var targetPrecision = 5;
  var targetMaxDistance = 200;
  
  // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
  private var lockCameraTimer = 0.0;
  
  // The current move direction in x-z
  private var moveDirection = Vector3.zero;
  // The current x-z move speed
  private var moveSpeed = 0.0;
  
  // The last collision flags returned from controller.Move
  private var collisionFlags : CollisionFlags; 
  
  // Are we moving backwards (This locks the camera to not do a 180 degree spin)
  private var movingBack = false;
  // Is the user pressing any keys?
  private var isMoving = false;
  
  private var isControllable = true;
  
  private var isTargetting : boolean = false;
  private var targetPoint : Vector3 = Vector3.zero;
  
  function Awake () {
      moveDirection = transform.TransformDirection(Vector3.forward);
  
      _animation = GetComponent(Animation);
      if(!_animation)
          Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");
  
      if(!idleAnimation) {
          _animation = null;
          Debug.Log("No idle animation found. Turning off animations.");
      }
      //_animation[idleAnimation.name] = idleAnimation;
  
      if(!walkAnimation) {
          _animation = null;
          Debug.Log("No walk animation found. Turning off animations.");
      }
      //_animation[walkAnimation.name] = walkAnimation;
  }
  
  function UpdateSmoothedMovementDirection () {
      var cameraTransform = Camera.main.transform;
  
      // Forward vector relative to the camera along the x-z plane    
      var forward = cameraTransform.TransformDirection(Vector3.forward);
      forward.y = 0;
      forward = forward.normalized;
  
      // Right vector relative to the camera
      // Always orthogonal to the forward vector
      var right = Vector3(forward.z, 0, -forward.x);
  
      var v = Input.GetAxisRaw("Vertical");
      var h = Input.GetAxisRaw("Horizontal");
  
      // Are we moving backwards or looking backwards
      if (v &lt; -0.2)
          movingBack = true;
      else
          movingBack = false;
  
      var wasMoving = isMoving;
      isMoving = Mathf.Abs (h) &gt; 0.1 || Mathf.Abs (v) &gt; 0.1;
  
      // Target direction relative to the camera
      var targetDirection = h * right + v * forward;
  
      // Lock camera for short period when transitioning moving &amp; standing still
      lockCameraTimer += Time.deltaTime;
      if (isMoving != wasMoving)
          lockCameraTimer = 0.0;
  
      // We store speed and direction seperately,
      // so that when the character stands still we still have a valid forward direction
      // moveDirection is always normalized, and we only update it if there is user input.
      if (targetDirection != Vector3.zero) {
          // If we are really slow, just snap to the target direction
          if (moveSpeed &lt; walkSpeed * 0.9) {
              moveDirection = targetDirection.normalized;
          }
          // Otherwise smoothly turn towards it
          else {
              moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
              moveDirection = moveDirection.normalized;
          }
      }
  
      // Smooth the speed based on the current target direction
      var curSmooth = speedSmoothing * Time.deltaTime;
  
      // Choose target speed
      //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
      var targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0);
  
      _characterState = CharacterState.Idle;
  
      // Pick speed modifier
      targetSpeed *= walkSpeed;
      _characterState = CharacterState.Walking;
  
      moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
  }
  
  
  function UpdateTargettedMovementDirection () {
      var cameraTransform = Camera.main.transform;
  
      var wasMoving = isMoving;
      isMoving = true;//Mathf.Abs (h) &gt; 0.1 || Mathf.Abs (v) &gt; 0.1;
  
      // Target direction relative to the camera
      // var targetDirection = h * right + v * forward;
      var targetDirection = Vector3.zero;
      targetDirection.x =  targetPoint.x - transform.position.x;
      targetDirection.z =  targetPoint.z - transform.position.z;
      targetDirection = targetDirection.normalized;
      //Debug.Log("Target direction is " + targetDirection);
  
      // Lock camera for short period when transitioning moving &amp; standing still
      lockCameraTimer += Time.deltaTime;
      if (isMoving != wasMoving)
          lockCameraTimer = 0.0;
  
      // We store speed and direction seperately,
      // so that when the character stands still we still have a valid forward direction
      // moveDirection is always normalized, and we only update it if there is user input.
      if (targetDirection != Vector3.zero) {
          // If we are really slow, just snap to the target direction
          if (moveSpeed &lt; walkSpeed * 0.9) {
              moveDirection = targetDirection.normalized;
          }
          // Otherwise smoothly turn towards it
          else {
              moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
              moveDirection = moveDirection.normalized;
          }
      }
  
      // Smooth the speed based on the current target direction
      var curSmooth = speedSmoothing * Time.deltaTime;
  
      // Choose target speed
      //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
      var targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0);
  
      _characterState = CharacterState.Idle;
  
      // Pick speed modifier
      targetSpeed *= walkSpeed;
      _characterState = CharacterState.Walking;
  
      moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);      
  }
  
  function Update() {
      if (!isControllable) {
          // kill all inputs if not controllable.
          Input.ResetInputAxes();
      }
  
      var distance : float = 0;
      if (Input.GetMouseButtonUp(0)) {
          if (isTargetting) {
              isTargetting = false;
              // Debug.Log("Stopped moving");
              FaceCamera();
          } else {
              var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
              var layerMask = 1 &lt;&lt; 8; // Terrain is layer 8
              var hit : RaycastHit;
              Physics.Raycast(Camera.main.transform.position, ray.direction, hit, 1000, layerMask);
              distance = Vector3.Distance(transform.position, hit.point);
              if (distance &lt;= targetMaxDistance &amp;&amp; hit.point != Vector3.zero) {
                  targetPoint = hit.point;
                  isTargetting = true;
                  // Debug.Log("Mouse up at hit " + hit.point + " at distance " + distance);
              } else {
                  isTargetting = false;
                  // Debug.Log("Ignored mouse up at hit " + hit.point + " at distance " + distance);
              }
          }
      }
  
      if (isTargetting) {
          // Debug.Log("Moving to " + targetPoint);
          distance = Vector3.Distance(transform.position, targetPoint);
          if (distance &lt; targetPrecision) {
              // Debug.Log("Reached point " + targetPoint + " at distance " + distance);
              isTargetting = false;
              FaceCamera();
          } else {
              UpdateTargettedMovementDirection();
          }
      } else {
          UpdateSmoothedMovementDirection();
      }
  
      // Calculate actual motion
      var movement = moveDirection * moveSpeed;
      movement *= Time.deltaTime;
  
      // Move the controller
      var controller : CharacterController = GetComponent(CharacterController);
      collisionFlags = controller.Move(movement);
  
      // ANIMATION sector
      if (_animation) {       
          if (controller.velocity.sqrMagnitude &lt; 0.1) {
              _animation.CrossFade(idleAnimation.name);
          } else {
              //_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed);
              _animation.CrossFade(walkAnimation.name);       
          }
      } else {
           Debug.Log("Animation is null!");
      }
      // ANIMATION sector
  
      // Set rotation to the move direction
      transform.rotation = Quaternion.LookRotation(moveDirection);
  }
  
  function OnControllerColliderHit (hit : ControllerColliderHit ) {
  //  Debug.DrawRay(hit.point, hit.normal);
      if (hit.moveDirection.y &gt; 0.01) 
          return;
  }
  
  function GetSpeed () {
      return moveSpeed;
  }
  
  function GetDirection () {
      return moveDirection;
  }
  
  function IsMovingBackwards () {
      return movingBack;
  }
  
  function GetLockCameraTimer () {
      return lockCameraTimer;
  }
  
  function IsMoving () : boolean {
      return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) &gt; 0.5;
  }
  
  function Reset () {
      gameObject.tag = "Player";
  }
  
  function FaceCamera() {
      var cameraTransform = Camera.main.transform;
  
      // Forward vector relative to the camera along the x-z plane    
      var forward = cameraTransform.TransformDirection(Vector3.forward);
      forward.y = 0;
      forward = forward.normalized;
  
      moveDirection = -forward;
  }
  </code></pre>
  
  <p><strong>Update 2:</strong> The settings used to create the animations are in these screenshots. Are they correct?
  <img src="https://i.stack.imgur.com/QNxx0.jpg" alt="Animation export setting 1"> 
  <img src="https://i.stack.imgur.com/uVZnZ.jpg" alt="Animation export setting 2"></p>