Rotation euler value changes to the previous value after getting resetted to 0

(you can skip to my 2. message, this code has been reworked)

I have this really simple code. It runs if I start wallrunning:

void TiltTowardsWall()
{
    if (wallLeft && playerModel.transform.rotation.z > -maximumTilt) // on the left wall and the max tilt isnt reached
    {
        playerModel.transform.Rotate(new Vector3(0f, 0f, -tiltsPerSecond) * tiltSpeed * Time.deltaTime);
    }
    if (wallRight && playerModel.transform.rotation.z < maximumTilt) // on the right wall and the max tilt isnt reached
    {
        playerModel.transform.Rotate(new Vector3(0f, 0f, tiltsPerSecond) * tiltSpeed * Time.deltaTime);
    }
}

This works so far.

I want to reset this tilt after the player leaves the wallrun state. This is my code:

void ResetPlayerTilt()
{
    Debug.Log("tilting called");

    if (playerModel.transform.rotation.z < 0) // Player is tilted to the left wall
    {
        playerModel.transform.Rotate(new Vector3(0f, 0f, tiltsPerSecond) * tiltSpeed * Time.deltaTime); // rotate to the other direction
        Debug.Log("lowering Leftwall tilt");

       if (playerModel.transform.rotation.eulerAngles.z > -2.5f) // -2.5f is the snap threshold
        { 
            playerModel.transform.rotation = Quaternion.Euler(0f, 0f, 0f); // could also use quaternion.identity
            Debug.Log("reset leftwall tilt");
        }

    }

    if (playerModel.transform.rotation.z > 0) // player is tilted to the right wall
    {
        playerModel.transform.Rotate(new Vector3(0f, 0f, -tiltsPerSecond) * tiltSpeed * Time.deltaTime);
        Debug.Log("Lowering Rightwall tilt");

        if (playerModel.transform.rotation.eulerAngles.z < 2.5f) // 2.5f is the snap threshold
        {
            playerModel.transform.rotation = Quaternion.Euler(0f, 0f, 0f); // could also use quaternion.identity
            Debug.Log("reset rightwall tilt");
        }

    }
        if (playerModel.transform.rotation.z == 0f) 
        {
            resetTilt = false;
            Debug.Log("resetTilt set to false");    
        }
}

The problem:

After lowering my tilt to 2.5f, the rotation gets set to 0f but a millisecond later right back to the value that it had previously, before it got set to 0.

And this function sometimes works as expected, sometimes the .z value stays 0, but only sometimes.

transform.rotation.z

This is not a Euler Angle and will not work. You’ve used it in a number of places, and it’s just going to be fundamentally wrong as it’s a part of a complex number (the Quaternion).

You should also consider tracking the euler rotations you’re using yourself, and never read them from the Transform. That way the values you read are not those that are interpreted from the Transform’s Quaternion.

You can read a little more about this here.

Oh wow, I didnt know that this is such a complex thing. I read a few articles and I changed my code. But I ended up with the same problem. It could be that I misunderstood your answer or implemented it incorrectly, but everything seems to work, except for the last frame.

I will describe the values.

The frame before the reset:

the transform.z is at 4.9f and the current angles.z is at 5.5f

a frame later:

the transform.z is at 0f and the current angles.z is at 2.6f

the outcome:

the transform.z is at 3.4f and the current angles.z is at 0f

(i couldnt upload 3 images, so i just made them into one, I hope this is readable)

this is the code that I changed:

    private void TiltTowardsWall()
    {

        Debug.Log("start tilting");

        if (wallLeft && currentEulerAngles.z > -maximumTilt) // on the left wall and the max tilt isnt reached
        {
            currentEulerAngles += new Vector3(0f, 0f, -tiltsPerSecond) * Time.deltaTime * tiltSpeed; // not sure if i should change it to -= and tiltsPerSecond, instead of += and -tiltsPerSecond
        }

        if (wallRight && currentEulerAngles.z < maximumTilt) // on the right wall and the max tilt isnt reached
        {
            currentEulerAngles += new Vector3(0f, 0f, tiltsPerSecond) * Time.deltaTime * tiltSpeed;
        }

        playerModel.transform.localEulerAngles = currentEulerAngles;

    }

    private void ResetPlayerTilt()
    {
        Debug.Log("reverse tilting");

        if (currentEulerAngles.z < 0f) // Player is tilted to the left wall
        {
            currentEulerAngles += new Vector3(0f, 0f, tiltsPerSecond) * Time.deltaTime * tiltSpeed;
            Debug.Log("lowering Leftwall tilt");

            if (currentEulerAngles.z > -2.5f) // -2.5f is the snap threshold
            {
                currentEulerAngles = Vector3.zero;
                Debug.Log("reset leftwall tilt");
            }

        }

        if (currentEulerAngles.z > 0f) // player is tilted to the right wall
        {
            currentEulerAngles += new Vector3(0f, 0f, -tiltsPerSecond) * Time.deltaTime * tiltSpeed;
            Debug.Log("Lowering Rightwall tilt");

            if (currentEulerAngles.z < 2.5f) // 2.5f is the snap threshold
            {
                currentEulerAngles = Vector3.zero;
                Debug.Log("reset rightwall tilt");
            }



        }

        playerModel.transform.eulerAngles = currentEulerAngles; // not sure where to put this

        if (currentEulerAngles.z == 0f) 
        {
            resetTilt = false;
            Debug.Log("resetTilt set to false");    
        }



    }

I hope that this is not time wasting and a noob-mistake, but I really dont know why this happens. Thanks in advance.

(

I finished the script now and I will post it down below just iiiin casee anybody has a similar problem.
Thanks to @Tidali for a similar solution in another thread <3

I ended up with two scripts:

public class SnapTilt : MonoBehaviour
{

    public bool MaximumRotationReached(GameObject gameObject, Vector3 maximumRotation)
    {
        if (Mathf.Floor(gameObject.transform.eulerAngles.x) == maximumRotation.x && Mathf.Floor(gameObject.transform.eulerAngles.y) == maximumRotation.y && Mathf.Floor(gameObject.transform.eulerAngles.z) == maximumRotation.z)
            return true;

        else
            return false;
    }

    public void RotateObject(GameObject gameObject, Vector3 rotationToChange)
    {
        gameObject.transform.Rotate(rotationToChange);
    }
}

and this is in my wallrun script:

private void TiltTowardsWall()
{

    if (wallLeft && !tiltS.MaximumRotationReached(playerModel, maximumTiltLeft)) 
    {
        tiltS.RotateObject(playerModel, maximumTiltLeft);
        startTilt = false;
    }

    if (wallRight && !tiltS.MaximumRotationReached(playerModel, maximumTiltRight))
    {
        tiltS.RotateObject(playerModel, maximumTiltRight);
        startTilt = false;
    }

}

private void ResetPlayerTilt()
{

    if (wasLeftWall && !tiltS.MaximumRotationReached(playerModel, noTilt))
    {
        tiltS.RotateObject(playerModel, tiltLeftReset);
        wasLeftWall = false;
        resetTilt = false;

    }

    if (wasRightWall && !tiltS.MaximumRotationReached(playerModel, noTilt))
    {
        tiltS.RotateObject(playerModel, tiltRightReset);
        wasRightWall = false;
        resetTilt = false;
    }

}