keeping the player upright

In my game I want to have the player able to go up inclined surfaces (I know that there is a limit to angle, and such), but I have the problem that when the angle of the player breaks a 45 it starts free spinning, and can easily end up upside down. I have implemented a input.GetKey to put the character right side up, but I need to figure out how to have a script do it automatically.

when I try this my character doesn’t rotate at all.
Note: on reset correction Y-rotation is preserved.

//current solution (character will not rotate at all about the x, or z axes.)
if((transform.rotation.eulerAngles.x<-180)||(transform.rotation.eulerAngles.x>180)||
    (transform.rotation.eulerAngles.z<-180)||(transform.rotation.eulerAngles.z >180)){
        // preserve Y rotation
        float currentLook = transform.rotation.eulerAngles.y;
        // put character to default rotation
        transform.rotation = Quaternion.identity;
        // re-introduce Y rotation
        transform.Rotate(0,currentLook,0);
}
// works as intended
if(Input.GetKey(".")){
    // preserve Y rotation
    float currentLook = transform.rotation.eulerAngles.y;
    // put character to default rotation
    transform.rotation = Quaternion.identity;
    // re-introduce Y rotation
    transform.Rotate(0,currentLook,0);
}

EDIT: currently I have my character wrapped in a box collider, and I would like to have it so that it can go up inclined planes, but I don’t want to have the player flip over.

does anyone have any ideas on how to keep the player from flipping over (might be using same logic for my AI agents if they have the same problem)

  • I still want the player to be able to rotate with respect to all axes,
  • once the transform breaks 90 with respect to either x, or z to have it go back to identity (then rotate by the previous y rotation)
  • and possibly let collision resolution(gravity) put it back to where it needs to be.

Performed test, and found that the understanding I was using for the eulerAngles was not the actual behavior.

The behavior of eulerAngles is such that they are only values from [0,360), and any negative(clockwise with respect to the give axis) that would make it go negative will instead place it to 360, and then start reducing. to demonstrate this the following code can be applied to a camera (a “Rotation” input axis would need to be introduced)

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {
    
    public float rotationScale = 40;
    
    // Update is called once per frame
    void Update () {
        float foward = Input.GetAxis("Vertical")  *Time.deltaTime*rotationScale;
        float side   = Input.GetAxis("Horizontal")*Time.deltaTime*rotationScale;
        float rot    = Input.GetAxis("Rotation")  *Time.deltaTime*rotationScale;
        transform.Rotate(foward,rot,side);
        print (transform.eulerAngles.ToString());
    }
}

So the corrected code from the question would be:

if(((transform.rotation.eulerAngles.x<270)&&(transform.rotation.eulerAngles.x>90))||
    ((transform.rotation.eulerAngles.z<270)&&(transform.rotation.eulerAngles.z>90))){
        // preserve Y rotation
        float currentLook = transform.rotation.eulerAngles.y;
        // put character to default rotation
        transform.rotation = Quaternion.identity;
        // re-introduce Y rotation
        transform.Rotate(0,currentLook,0);
}

Will keep the player from passing a 90 degree rotation with respect to those 2 axis, though in some situations it might be beneficial to break these apart instead of using a logical or (||) to minimize the need to have collision resolution clean up after the fact.