I’m using Input.acceleration in “landscape left” orientation. I need it to act the same in “landscape right” orientation.
When I’m testing via the Unity Remote 4, all axes get “converted” by the device orientation automatically and it acts as it should, no matter the orientation.
The problems arise when I create the Android build: If I run the game in “landscape left”, axes are working fine. When I flip the running app in “landscape right”, the X axis gets inverted, and Y goes from - to +. Z axis is ok. Everything also works if i run the app while in “landscape right”, but same happens when I turn the device to “landscape left”.
I recently installed Unity 5.1.2 and axis conversion thing worked in 4.6!
Does anyone have a clue if it’s a bug, or it’s standard “new” behaviour?
Does anyone have a workaround for this?
find out how to use “unity’s ability” to correct axes according to screen rotation
disable autorotation, have only “landscape left”
rewrite the accelerometer class to include device turning from filtering Input.deviceOrientation to DeviceOrientation.LandscapeLeft and DeviceOrientation.LandscapeRight
Basically what this does is compensate the accelerometer not re-adjusting the axes by itself as they should be on screens orientations (unity bug). This script is switching between two types of accelerometer calculations and calibrations; normal and inverted.
Have in mind that this is just an “addon” for your working accelerometer calculation, not the complete accelerometer solution.
// STARTUP DEVICE ORIENTATION (if device is on the table, unity runs the app in LandscapeLeft)
public DeviceOrientation deviceOrientation = DeviceOrientation.LandscapeLeft;
// treshold (if z < 0) at which android will start the application in landscape.right orientation
public float startuplYswitchTreshold = -0.5f;
// accelerometer y axis limit at which the device orientation switches the orientation
public float accelYswitchTreshold = 0.85f;
// flag that initiates switch in calculation
private bool isAccelNormalFlag = true;
// accelerometer input
private Vector3 accelRaw;
void Start () {
CheckStartupDeviceOrientation ();
}
void Update () {
AccelerometerUpdate();
}
// called usually from gui
void OnClick () {
Calibrate ();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEVICE ORIENTATION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GET INITIAL DEVICE ORIENTATION
private void CheckStartupDeviceOrientation (){
Vector3 accelRaw = Input.acceleration.normalized;
if (accelRaw.y < startuplYswitchTreshold && accelRaw.z < 0) deviceOrientation = DeviceOrientation.LandscapeRight;
else deviceOrientation = DeviceOrientation.LandscapeLeft;
}
// GET DEVICE ORIENTATION
public DeviceOrientation GetDeviceOrientation () {
switch (Input.deviceOrientation) {
case DeviceOrientation.LandscapeLeft:
currentDeviceOrientation = Input.deviceOrientation;
break;
case DeviceOrientation.LandscapeRight:
currentDeviceOrientation = Input.deviceOrientation;
break;
}
return currentDeviceOrientation;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ACCELEROMETER INVERSION CHECK
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void AccelerometerUpdate() {
accelRaw = Input.acceleration.normalized;
if (IsAccelerometerNormal()) AccelerometerCalculationNormal ();
else AccelerometerCalculationInverted ();
}
// CHECK IF ACCELEROMETER NEEDS INVERSION
private bool IsAccelerometerNormal () {
deviceOrientation = ScreenManager.Instance.GetDeviceOrientation ();
switch (deviceOrientation){
case DeviceOrientation.LandscapeLeft:
return GetAccelerometerNormalFlag();
break;
case DeviceOrientation.LandscapeRight:
return GetAccelerometerNormalFlag();
break;
default:
return true; //fallback
}
}
// GET NORMAL FLAG
// if it's normal, check if it should go to inverted
// if it's inverted, check if it needs to go back to normal)
private bool GetAccelerometerNormalFlag (){
if (isAccelNormalFlag) {
isAccelNormalFlag = IsAccelerometerValueNormal();
return isAccelNormalFlag;
}
else {
isAccelNormalFlag = ShouldAccelerometerReturnToNormal();
return isAccelNormalFlag;
}
}
// ARE VALUES NORMAL (false = they should be inverted)
private bool IsAccelerometerValueNormal (){
// Y axis is pitch, use this to detect the orientation and invert accelerometer calculation if necessary
// IN NORMAL MODE:
// Y < 0 is facing up, -1 facing you, 0 facing down
// Z > 0 is facing down, Z < 0 is facing up, 0 iz facing you
if ((accelRaw.y < accelYswitchTreshold && accelRaw.z < 0) || // from face up to 45 away from you (screen orientation switch then)
(accelRaw.y < 0 && (accelRaw.z < 0 || accelRaw.z > 0)) || // from facing up, over facing you, to facing down
(accelRaw.y < accelYswitchTreshold && accelRaw.z > 0) // from face down to 45 away from you (screen orientation switch then)
) return true;
return false; //fallback
}
// ARE VALUES INVERTED (false = they should be normal)
private bool ShouldAccelerometerReturnToNormal () {
// WORKAROUND UNITY'S AXIS RECALIBRATION BUG ON SCREEN ROTATION
// Y axis is pitch, use this to detect the orientation and invert accelerometer calculation if necessary
// IN INVERTED MODE
// Y < 0 is facing up, 1 facing you, 0 facing down
// Z > 0 is facing down, Z < 0 is facing up, 0 iz facing you
if ((accelRaw.y > -accelYswitchTreshold && accelRaw.z < 0) || // from face up to 45 away from you (screen orientation switch then)
(accelRaw.y > 0 && (accelRaw.z < 0 || accelRaw.z > 0)) || // from facing up, over facing you, to facing down
(accelRaw.y > -accelYswitchTreshold && accelRaw.z > 0) // from face down to 45 away from you (screen orientation switch then)
) return false;
return true; //fallback
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ACCELEROMETER CALCULATIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void AccelerometerCalculationNormal (){
// DO NORMAL CALCULATIONS HERE
}
private void AccelerometerCalculationInverted (){
// DO INVERTED CALCULATIONS HERE
// X AND Y AXIS NEED TO BE INVERTED
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// CALIBRATION CALCULATIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Calibrate() {
if (IsAccelerometerNormal()) CalibrateNormal ();
else CalibrateInverted ();
}
private void CalibrateNormal (){
// DO NORMAL CALIBRATION HERE
}
private void CalibrateInverted (){
// DO INVERTED CALIBRATION HERE
}