Right! Problem(s) solved. Updated (solution) code
and original confused floundering preserved below.
Poster Competence: Complete noob.
The Objective: Character moves and animates in 3D space (scripts below) and when motionless (with no input) stands still (upright) and plays an idle animation.
The Result: Character moves and animates in 3D space and when motionless ROTATES 90 DEGREES AND FLOATS ABOUT A METRE OFF THE GROUND, FACING THE GROUND while playing idle animation. Moving returns character to correct orientation (hurrah), ceasing movement returns character to 90 degree state (boo). (Short answer - gravity value was increasing the downward direction variable from 0, causing the SetLookRotation command to aim the character at the ground)
Summary: what the hell I don't even
Character is skinned and animated with location and rotation information applied before saving in Blender. Character was rescaled SLIGHTLY in Unity.
Motion/Animation scripts derived from the following: http://unity3d.com/support/documentation/ScriptReference/CharacterController.Move.html http://unity3d.com/support/documentation/Manual/Character-Animation.html
Movement Script (SOLVED!):
/// This script moves the character controller forward
/// and sideways based on the arrow keys.
/// It also jumps when pressing space.
/// Make sure to attach a character controller to the same game object.
/// It is recommended that you make only one call to Move or SimpleMove per frame.
var speed : float = 6.0;
var jumpSpeed : float = 8.0;
var gravity : float = 20.0;
private var moveDirection : Vector3 = Vector3.zero;
function Update() {
var controller : CharacterController = GetComponent(CharacterController);
if (controller.isGrounded) {
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
moveDirection *= speed;
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
// Owen Reynolds change --> Copies moveDirection to moveOrientation and sets Y to 0.
// Awesome.
if (moveDirection.x !=0 || moveDirection.z !=0)
{
var moveOrientation : Vector3 = moveDirection;
moveOrientation.y = 0;
var rotation = transform.rotation;
rotation.SetLookRotation(moveOrientation);
transform.rotation = rotation;
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
}
Animation Script (SOLVED!):
function Start ()
{
//Set all animations to loop
animation.wrapMode = WrapMode.Loop;
// except using
animation["revEdaStandAction"].wrapMode = WrapMode.Once;
// Put idle and walk into lower layers (The default layer is always 0)
// This will do two things
// - Since shoot and idle/walk are in different layers they will not affect each other's playback when calling CrossFade
// - Since shoot is in a higher layer, the animation will replace idle/walk animations when faded in.
animation["revEdaWalk01"].layer = 1;
animation["revEdaStandAction"].layer = 2;
// Stop animations that are already playing
// (in case user forgot to disable play automatically)
animation.Stop();
}
function Update ()
{
if(Input.GetAxis ("Horizontal") !=0 || Input.GetAxis ("Vertical") !=0)
{
animation.CrossFade ("revEdaWalk01");
//Debug.Log("GetAxis is !0");
}
// Still ended up using two Walk 'if's as character continued to walk while motionless.
// The following checks that character is motionless on x&z, STOPS the walk anim & plays
// the anim revEdaIdle. Need to investigate blends...!
if(Input.GetAxis ("Horizontal") ==0 && Input.GetAxis ("Vertical") == 0)
{
animation.Stop("revEdaWalk01");
animation.CrossFade ("revEdaIdle01");
//Debug.Log("GetAxis is 0");
}
// Using
if(Input.GetButtonUp ("Fire1"))
{
animation.CrossFade ("revEdaStandAction");
}
}
Character game object has Transform, Animation, Character Controller and the two scripts above attached.
There are a few Unity Answers posts & Unity Forum posts which seem kinda close to what I'm asking, but try as I might I haven't been able to extract a solution to my problem. The closest thing to a solution I've found is a suggestion to flip the character z and y axis in Blender and, really...'really?' In Unity? In a program user-friendly thus far? (Not an issue)
Looking forward to upvoting a helpful answer. Thanks, guys. =) (GOT ONE! Cheers, Owen!)
I'm no blender expert but make sure Y is your up axis when exporting in blender. Also make sure your character has no transforms in blender. I know in Maya there is a freeze transforms option, I'm sure Blender has something similar. You say 'Character is skinned and animated with location and rotation information applied before saving in Blender', are these transforms only applied to your animations? Or to your character as well?
– MeltdownJustin - The idle animation is of the character standing upright, with subtle breathing motion and hand flexing. Due to my noobness, it plays about four time the speed I intended so it looks like my character is tweaking badly. However, this doesn't appear to have any bearing on the character's 90degree orientation change. Second comment to follow for Meltdown.
– Reverend-SpeedMeltdown - Blender's 'apply locrot' (location/rotation) is equivalent to Maya's 'freeze transforms' action, AFAIK. AFIK, transforms have been applied animations & character. Anims for walking and touching work fine - as does the idle anim, but not the model orientation when still. Can see no relevant difference in anim construction within Blender. Model is UPRIGHT in Unity until Play mode is activated. GAH TEXT LIMIT.
– Reverend-Speed