- Home /
Original Blender character faces ground when not walking
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 $$anonymous$$aya 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?
Justin - 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 $$anonymous$$eltdown.
$$anonymous$$eltdown - Blender's 'apply locrot' (location/rotation) is equivalent to $$anonymous$$aya's 'freeze transforms' action, AFAI$$anonymous$$.
AFI$$anonymous$$, 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.
$$anonymous$$odel is UPRIGHT in Unity until Play mode is activated.
GAH TEXT LI$$anonymous$$IT.
Blender follows the Cartesian coordinate system in 3D space of placing Z on the vertical axis. Unity does not. Read some comments pointing to this as a poss. problem, but most people seem to get along fine with it - all indications up to this point seemed to suggest that the Unity .blend importer corrected for axis differences between the two programs.
Will look into this, but find it improbable that Unity & Blender (which work together so well in most cases) require me to reorientate models & anims before import.
That said, thanks to both you and $$anonymous$$eltdown for your responses! Obliged!
Answer by Owen-Reynolds · Mar 29, 2011 at 04:13 PM
I think the problem is the SetLookRotation (bottom of 1st code block.) You are always moving a tiny bit down due to gravity. If you are stopped, you count as moving straight down. If you are coasting to a stop, you count as moving 45 degrees down.
You probably want to ignore your y-speed completely. Of course, you can't get rid of gravity or really mess with ySpeed, or else you will never come down from a jump. I'd try:
if(md.x!=0 || md.z!=0) { // not moving on flat map. We could be jumping up, Who cares.
// Use COPY of moveDirection, with y gone:
Vector3 md = movedirection;
md.y = 0;
blah, blah SetLookRotation(md); // look in the FLAT way we are moving
}
The fact your Walk looks OK sort of proves you have the export axis' sorted out. I had to use the blender FBX exporter explicitly, and there is a button that says "FlipY/-Z" (takes care of Meltdown's comment about wrong axis.)
There's a small bug in your animation code: if you aren't moving sideways, you idle. Maybe combine the two Walk ifs:
if(horiz!=0 || vert!=0) walk
else idle
Hi Owen! Thanks for the response. Slightly confused with the md & horiz abbreviations, but I'm onto your crazy program$$anonymous$$g tricks. =) Results as follows:
*Character now does not I$$anonymous$$$$anonymous$$EDIATELY flip 90 degrees in X on Play mode start. *Character walks forwards (W) and backwards (S) without turning on axis - but now doesn't change orientation at all - keeps facing forwards. This changes when you move to the side - A & D. Now character behaves as before (including forward & backward movement+anims)... but sometimes char doesn't quite turn 90.
Will update code above & investigate gravity.
$$anonymous$$ore confused now. *Changing gravity settings from 20 to 0 and values inbetween alters the frequency of the x axis 90degree rot. The closer to 0g, the fewer 90degree problems there are, though the character will still occasionally rotate to 45-90degrees on stopping. Setting gravity to 0 makes the character immobile - can't move with WASorD.
*Translation on Z axis (W/D) does not turn character in that direction, but neither does character EVER flip 90 when moving on this axis. x axis flips only occur on x axis movement.
It's possible to have the character change facing from forward to backward and backward to forward, but only by moving him in the Z axis during or immediately after translating him in x. Frustrating. Has to be an obv solution - still working on it. Willing to send files to someone who can help me sort this out. I'm no programmer, but I'm annoyed that something this simple should be getting in my way...
Revised answer to respond to comment. Also, you checked x twice, which means only sideways movement triggers a turn. It works immediately after a sideways move, since you are still coasting.
And a shiny 'tick' mark goes to you. =) $$anonymous$$uch obliged. Had been playing around with copying the moveDirection variable and trying to estrange it from gravity calculations... but somehow the BLINDINGLY OBVIOUS method of setting y to '0' didn't occur to me. Thanks for your patience. Have also altered the Anim script as the character kept walking while standing still - re-added the second if statement to check that X&Z are at 0, then stopping the walk anim. I fear this is more of a hack than a solve and I need to investigate anim blending more, but for now it's a win. Thanks!
Answer by visakh123 · Apr 23, 2014 at 08:44 AM
check out this link
http://answers.unity3d.com/questions/692807/how-to-make-character-run-along-a-slope-road-in-un.html