Search Unity

Unity accelerometer and screen/device orientation issue

Discussion in 'Scripting' started by illa3d, Aug 11, 2015.

  1. illa3d

    illa3d

    Joined:
    Dec 7, 2014
    Posts:
    17
    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?

    Thanks!
     
  2. illa3d

    illa3d

    Joined:
    Dec 7, 2014
    Posts:
    17
    Solutions I have so far:
    - 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`
     
  3. illa3d

    illa3d

    Joined:
    Dec 7, 2014
    Posts:
    17
    So far "quick fix" of changing orientation while running android app:
    - while in app change to another orientation to the one app started in
    - press menu key to return to main android page
    - long press menu key to display list of appssee the applications list, select your running application
    - accelerometer axis recalculated :)

    I'm working on a checking mechanism in code, I'll share it when I'm done.
     
  4. illa3d

    illa3d

    Joined:
    Dec 7, 2014
    Posts:
    17
    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.

    Code (CSharp):
    1.  
    2.   // STARTUP DEVICE ORIENTATION (if device is on the table, unity runs the app in LandscapeLeft)
    3.   public DeviceOrientation deviceOrientation = DeviceOrientation.LandscapeLeft;
    4.  
    5.   // treshold (if z < 0) at which android will start the application in landscape.right orientation
    6.   public float startuplYswitchTreshold = -0.5f;
    7.  
    8.   // accelerometer y axis limit at which the device orientation switches the orientation
    9.   public float accelYswitchTreshold = 0.85f;
    10.  
    11.   // flag that initiates switch in calculation
    12.   private bool isAccelNormalFlag = true;
    13.  
    14.    // accelerometer input
    15.   private Vector3 accelRaw;
    16.  
    17.   void Start () {
    18.   CheckStartupDeviceOrientation ();
    19.   }
    20.  
    21.   void Update () {
    22.   AccelerometerUpdate();
    23.   }
    24.  
    25.   // called usually from gui
    26.   void OnClick () {
    27.   Calibrate ();
    28.   }
    29.  
    30.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    31.   // DEVICE ORIENTATION
    32.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    33.  
    34.   // GET INITIAL DEVICE ORIENTATION
    35.   private void CheckStartupDeviceOrientation (){
    36.   Vector3 accelRaw = Input.acceleration.normalized;
    37.   if (accelRaw.y < startuplYswitchTreshold && accelRaw.z < 0) deviceOrientation = DeviceOrientation.LandscapeRight;
    38.   else deviceOrientation = DeviceOrientation.LandscapeLeft;
    39.   }
    40.  
    41.  
    42.   // GET DEVICE ORIENTATION
    43.   public DeviceOrientation GetDeviceOrientation () {
    44.   switch (Input.deviceOrientation) {
    45.   case DeviceOrientation.LandscapeLeft:
    46.   currentDeviceOrientation = Input.deviceOrientation;
    47.   break;
    48.   case DeviceOrientation.LandscapeRight:
    49.   currentDeviceOrientation = Input.deviceOrientation;
    50.   break;
    51.   }
    52.   return currentDeviceOrientation;
    53.   }
    54.  
    55.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    56.   // ACCELEROMETER INVERSION CHECK
    57.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    58.  
    59.   private void AccelerometerUpdate() {
    60.   accelRaw = Input.acceleration.normalized;
    61.   if (IsAccelerometerNormal()) AccelerometerCalculationNormal ();
    62.   else AccelerometerCalculationInverted ();
    63.   }
    64.  
    65.   // CHECK IF ACCELEROMETER NEEDS INVERSION
    66.   private bool IsAccelerometerNormal () {
    67.   deviceOrientation = ScreenManager.Instance.GetDeviceOrientation ();
    68.   switch (deviceOrientation){
    69.   case DeviceOrientation.LandscapeLeft:
    70.   return GetAccelerometerNormalFlag();
    71.   break;
    72.   case DeviceOrientation.LandscapeRight:
    73.   return GetAccelerometerNormalFlag();
    74.   break;
    75.   default:
    76.   return true; //fallback
    77.   }
    78.   }
    79.  
    80.   // GET NORMAL FLAG
    81.   // if it's normal, check if it should go to inverted
    82.   // if it's inverted, check if it needs to go back to normal)
    83.   private bool GetAccelerometerNormalFlag (){
    84.   if (isAccelNormalFlag) {
    85.   isAccelNormalFlag = IsAccelerometerValueNormal();
    86.   return isAccelNormalFlag;
    87.   }
    88.   else {
    89.   isAccelNormalFlag = ShouldAccelerometerReturnToNormal();
    90.   return isAccelNormalFlag;
    91.   }
    92.   }
    93.  
    94.   // ARE VALUES NORMAL (false = they should be inverted)
    95.   private bool IsAccelerometerValueNormal (){
    96.   // Y axis is pitch, use this to detect the orientation and invert accelerometer calculation if necessary
    97.   // IN NORMAL MODE:
    98.   // Y < 0 is facing up, -1 facing you, 0 facing down
    99.   // Z > 0 is facing down, Z < 0 is facing up, 0 iz facing you
    100.   if ((accelRaw.y < accelYswitchTreshold && accelRaw.z < 0) || // from face up to 45 away from you (screen orientation switch then)
    101.   (accelRaw.y < 0 && (accelRaw.z < 0 || accelRaw.z > 0)) || // from facing up, over facing you, to facing down
    102.   (accelRaw.y < accelYswitchTreshold && accelRaw.z > 0) // from face down to 45 away from you (screen orientation switch then)
    103.   ) return true;
    104.   return false; //fallback
    105.   }
    106.  
    107.   // ARE VALUES INVERTED (false = they should be normal)
    108.   private bool ShouldAccelerometerReturnToNormal () {
    109.   // WORKAROUND UNITY'S AXIS RECALIBRATION BUG ON SCREEN ROTATION
    110.   // Y axis is pitch, use this to detect the orientation and invert accelerometer calculation if necessary
    111.   // IN INVERTED MODE
    112.   // Y < 0 is facing up, 1 facing you, 0 facing down
    113.   // Z > 0 is facing down, Z < 0 is facing up, 0 iz facing you
    114.   if ((accelRaw.y > -accelYswitchTreshold && accelRaw.z < 0) || // from face up to 45 away from you (screen orientation switch then)
    115.   (accelRaw.y > 0 && (accelRaw.z < 0 || accelRaw.z > 0)) || // from facing up, over facing you, to facing down
    116.   (accelRaw.y > -accelYswitchTreshold && accelRaw.z > 0) // from face down to 45 away from you (screen orientation switch then)
    117.   ) return false;
    118.   return true; //fallback
    119.   }
    120.  
    121.  
    122.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    123.   // ACCELEROMETER CALCULATIONS
    124.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    125.  
    126.   private void AccelerometerCalculationNormal (){
    127.   // DO NORMAL CALCULATIONS HERE
    128.   }
    129.  
    130.   private void AccelerometerCalculationInverted (){
    131.   // DO INVERTED CALCULATIONS HERE
    132.   // X AND Y AXIS NEED TO BE INVERTED
    133.   }
    134.  
    135.  
    136.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    137.   /// CALIBRATION CALCULATIONS
    138.   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    139.  
    140.   public void Calibrate() {
    141.   if (IsAccelerometerNormal()) CalibrateNormal ();
    142.   else CalibrateInverted ();
    143.   }
    144.  
    145.   private void CalibrateNormal (){
    146.   // DO NORMAL CALIBRATION HERE
    147.   }
    148.  
    149.   private void CalibrateInverted (){
    150.   // DO INVERTED CALIBRATION HERE
    151.   }
     
    Last edited: Aug 13, 2015