0
\$\begingroup\$

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...

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

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.

\$\endgroup\$
6
  • \$\begingroup\$ Could you post an example? \$\endgroup\$ Jul 9, 2015 at 0:10
  • \$\begingroup\$ 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. \$\endgroup\$
    – Stephan
    Jul 9, 2015 at 15:53
  • \$\begingroup\$ @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". \$\endgroup\$
    – Stephan
    Jul 9, 2015 at 17:40
  • \$\begingroup\$ Yeah I've tried looking for OnInput() and OnKey(). It doesn't seem like those exist \$\endgroup\$ Jul 10, 2015 at 23:37
  • \$\begingroup\$ 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 \$\endgroup\$
    – Stephan
    Jul 20, 2015 at 14:28
0
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ 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. \$\endgroup\$ Jul 4, 2015 at 21:50
  • \$\begingroup\$ @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. \$\endgroup\$
    – DMGregory
    Jul 5, 2015 at 13:01
  • \$\begingroup\$ Yeah, that would work. Hang on I have a script that does that I will edit my answer \$\endgroup\$ Jul 5, 2015 at 19:39
  • \$\begingroup\$ 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... \$\endgroup\$ Jul 6, 2015 at 23:03
  • \$\begingroup\$ 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) \$\endgroup\$ Jul 9, 2015 at 21:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .