Skip to main content
typo
Source Link
DMGregory
  • 136.3k
  • 22
  • 247
  • 373

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them.

So it's best to never use .eulerAngles as the input to a calculation. Treat this field as write-only. Never read with an aim to modify the value or make decisions based on the value, or you are extremely liable to make a mistake.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 -+ radians * Mathf.Rad2Deg;
}

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them.

So it's best to never use .eulerAngles as the input to a calculation. Treat this field as write-only. Never read with an aim to modify the value or make decisions based on the value, or you are extremely liable to make a mistake.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 - radians * Mathf.Rad2Deg;
}

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them.

So it's best to never use .eulerAngles as the input to a calculation. Treat this field as write-only. Never read with an aim to modify the value or make decisions based on the value, or you are extremely liable to make a mistake.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 + radians * Mathf.Rad2Deg;
}
added 164 characters in body
Source Link
DMGregory
  • 136.3k
  • 22
  • 247
  • 373

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them. 

So it's best to never use .eulerAngles as the input to a calculation. Treat this field as write-only. Never read with an aim to modify the value or make decisions based on the value, or you are extremely liable to make a mistake.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 - radians * Mathf.Rad2Deg;
}

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them. So it's best to never use .eulerAngles as the input to a calculation.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 - radians * Mathf.Rad2Deg;
}

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them. 

So it's best to never use .eulerAngles as the input to a calculation. Treat this field as write-only. Never read with an aim to modify the value or make decisions based on the value, or you are extremely liable to make a mistake.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 - radians * Mathf.Rad2Deg;
}
Source Link
DMGregory
  • 136.3k
  • 22
  • 247
  • 373

Remember, Euler angles are a fiction, made for ease of data input in the scene editor. They're not stored under the hood, so when you read an Euler angle triplet, it's converted on the fly from the actual stored quaternion representation.

The quaternion will always give you consistent behaviour to calculate with - that's why we use them. The conversion from an orientation to Euler angles is arbitrary - many different Euler angle triplets correspond to the same orientation, and the engine has to pick wrap-around points somewhere, quite likely not where you want them. So it's best to never use .eulerAngles as the input to a calculation.

If you have an object that you only ever rotate around the x axis, you can compute its rotation about that axis by checking which direction its .forward vector is pointing:

float GetXDegrees(this Transform t) {
    // Get the angle about the world x axis in range -pi to +pi,
    // with 0 corresponding to a 180 degree rotation.
    var radians = Mathf.Atan2(t.forward.y, -t.forward.z);

    // Map to range from 0 to 360 degrees,
    // with 0 corresponding to no rotation.
    return 180 - radians * Mathf.Rad2Deg;
}