Player rotation issues (Player returns to default forward rotation after releasing keys)

So basically what is happening is that my player rotates and faces the direction that he is currently being steered toward (which is wonderful). But after I release, let's say the A key, meaning he is currently facing and moving to the left, he goes back to facing forward after the key is released.

Here is my code:

public class PlayerMovement : MonoBehaviour {
public bool isGrounded;
private float distToGround;
private Vector3 v;
private Vector3 h;
public float speed;

Rigidbody rb;
Collider col;

void Start() {
rb = GetComponent<Rigidbody>();
col = GetComponent<Collider>();
distToGround = col.bounds.extents.y;
}

void Update() {
if (Physics.Raycast (transform.position, -Vector3.up, distToGround + 0.1f)) isGrounded = true; else isGrounded = false;
if (isGrounded) {
v = new Vector3(0, 0, Input.GetAxis("Vertical")) * speed;
h = new Vector3(Input.GetAxis("Horizontal"), 0, 0) * speed;
rb.MovePosition(rb.position + v * Time.deltaTime);
rb.MovePosition(rb.position + h * Time.deltaTime);

//This deals with all the rotation
Vector3 direction = new Vector3( Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical") );
Quaternion rotation = Quaternion.LookRotation(direction, Vector3.up);
transform.rotation = rotation;
}
}
}


I obviously know that the reason this is happening is because the rotation is being set to the axis currently being pressed, so when I release any key, the rotation goes back to the original position. I just can't quite figure out how to fix it...

I think the issue is that the input is being polled every frame as part of the Update().

I would suggest pulling the input from the Update() and using input callbacks instead. That way the input is only polled when fired, and not every frame. That should cause the direction to only update with input changes, and the Update() will continue to render the same direction until the value is changed the next time the callback fires.

Unity doesn't have callbacks, I forgot that I emulate them. This is going to take some more thought on my part. I will update soon.

If your game is a top down on an 8 point compass this gets a lot easier, but I'm trying to come up with a generalized solution.

• Could you post an example? Jul 9 '15 at 0:10
• Yeah but id have to pull up the API and I'm behind a firewall at work. I'll update the answer when i get home. Jul 9 '15 at 15:53
• @Qwertyq To get you started, go to the API for Unity and look up OnInput() or OnKey(), you can also try searching with the word "callback". Jul 9 '15 at 17:40
• Yeah I've tried looking for OnInput() and OnKey(). It doesn't seem like those exist Jul 10 '15 at 23:37
• I had a funeral and haven't been able to get to working this out yet. I'll be working on it this week. I want ot make sure what I say here actually works as intended and will be making a test project to prototype. Even if you've figured it out, i'll be posting here for posterity Jul 20 '15 at 14:28

Try adding an if statement saying if neither of the axis are equal to zero then change the rotation, this would eliminate facing forwards when there is 0 on each axis.

if(direction != Vector3.zero)
{Quaternion rotation = Quaternion.LookRotation(direction, Vector3.up);
transform.rotation = rotation;
}


Hope this helped.

Here is another solution on Velocity;

    if (direction != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(direction);
}


Hope this is better.

• Yeah I actually tried that. But it doesn't quite work. If I'm moving in a diagonal direction or something askew from the axis -1 or 1, then when I release the keys, the player rotates to the nearest -1 or 1 axis. It doesn't stay where I released the player from. Jul 4 '15 at 21:50
• @Qwertyq sounds like one axis is zeroing-out before the other. Have you tried setting the rotation based on the velocity instead (with a minimum threshold)? Other alternatives are to accumulate your direction vector over a few frames, and take a moving average rather than an instantaneous sample. Jul 5 '15 at 13:01
• Yeah, that would work. Hang on I have a script that does that I will edit my answer Jul 5 '15 at 19:39
• I've tried what you posted in your edit. It still does the same thing. If I don't have it at a perfect angle, the player goes back to the closest rotation of -1, 1 or a 45 degree angle... Jul 6 '15 at 23:03
• You could try declaring both horizontal and vertical at the same time. use "Vector3 Movement = new Vector3(Input.getAxis("Horizontal"),0,Input.getAxis("Vertical")) * speed;" But this is a guess. I don't know if you have other sections interfering as well. It may be that one script is called before another(so check the script execution order under preferences) Jul 9 '15 at 21:03