My problem is that a custom walk animation I have set in the third person controller of Unity3D is not shown.
The animation is imported from a FBX file with the [email protected] 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.
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.
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.
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?
Update: 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 _animation.CrossFade
are getting called at the expected times. Using Play
or Blend
instead doesn't help. There are no errors logged in the console.
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.
// 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 < -0.2)
movingBack = true;
else
movingBack = false;
var wasMoving = isMoving;
isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;
// Target direction relative to the camera
var targetDirection = h * right + v * forward;
// Lock camera for short period when transitioning moving & 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 < 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) > 0.1 || Mathf.Abs (v) > 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 & 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 < 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 << 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 <= targetMaxDistance && 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 < 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 < 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 > 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")) > 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;
}
Update 2: The settings used to create the animations are in these screenshots. Are they correct?
Not (yet :-) an answer but I need more space and images.
Since 3.5 Unity3d the way to handle imports based on [email protected] notation has changed and some people reported trouble (s. for example BIG Unity 3.5.0f1 problem with Skinned Rig - Major FAIL). The problem arises when a 2nd root bone comes to play but I could solve this by dragging the animations to the model file prefab (most of my animations are contained in the model and the remaining 2 are no big pain).
Just to be really sure that I understood your answer in the comments section right, you have something like this:
That means:
Assuming this is fine some more suggestions:
Debug.Log ("Walk: " + player.animation.IsPlaying ("Walk"));
[Update]
Let's look at the import settings. Do you have Split Animations checked and are there maybe wrong values entered at Start and End like 1-1?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With