Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[sharing] gyroscope-controlled camera on iPhone 4

Discussion in 'iOS and tvOS' started by phoberman, Aug 1, 2011.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,817
    Hye phoberman,

    Thanks heaps for sharing this scene, I would have been pretty stuck trying to figure it out myself. Quaternions are scary!

    I'm trying to expand on it a little though and I was wondering, does anyone know how i could "calibrate" the result on an arbitrary angle? Say if you are on your couch and your device is on a weird angle you could recalibrate it so that angle would be the reset rotation.
    I've tried a few approaches but I'm not really getting anywhere :(

    Any ideas?
    Thanks
    Pete
     
  2. ilya_ca

    ilya_ca

    Joined:
    Nov 19, 2011
    Posts:
    274
    Hi,
    How can I roll my camera with this script? I have a camera that's looking to some object and I want to always keep the camera parallel to the floor.

    Thanks!
     
  3. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Wow, you had to use the Java call interface - is there really no way to just check for ScreenOrientation in Unity only ?

     
  4. quitebuttery

    quitebuttery

    Joined:
    Mar 12, 2011
    Posts:
    327
    No--because Unity compensantes for the natural angle to report if it's Landscape or Portrait. You need to figure out the natural orientation--and the only way to do it is to do it at the Android API level to get the rotation from 'natural'. It's actually a bug in Unity--the Gyro should return the same orientations regardless of how the device is oriented and what platform it's on. I guess they did that for the accelerometer, but forgot to do it for the gyro.
     
  5. darkmax

    darkmax

    Joined:
    Feb 21, 2012
    Posts:
    83
    hi, i'm trying to use this for a RA application but, i can't match the virtual north with the real north, any suggestions about this? i tried Input.compass.magneticHeading, but the lecture is to shaky but maybe i need to make a filter for this but i'm not sure if this the correct way of do it, so if any have any ideas i will appreciate.
     
  6. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Is this broken for Unity 3.5.6 Android?

     
  7. quitebuttery

    quitebuttery

    Joined:
    Mar 12, 2011
    Posts:
    327
    Supposedly the Gyro has been fixed in 3.5.6 so you don't need to flip it anymore based on orientation, or device. I haven't gone back to re-write my gyro camera code but I'm pretty sure none of this works anymore in 3.5.6.
     
  8. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Tried on iOS, no changes due to orientation issues although reported as fixed in "What´s new":

    "iOS: Fixed various orientation issues."

    Does anyone get additional rotation of the camera by mouse, as reported in the script, working in vertical direction?
    Horizontal rotation works fine:

    Code (csharp):
    1. // Also creates a grandparent (camGrandparent) which can be rotated with localEulerAngles.y
    2.  
    3. // This node allows an arbitrary heading to be added to the gyroscope reading
    4.  
    5. // so that the virtual camera can be facing any direction in the scene, no matter what the phone's heading
    EDIT: Mouse rotation solved
     
    Last edited: Oct 12, 2012
  9. kaz2057

    kaz2057

    Joined:
    Jan 18, 2011
    Posts:
    326
    anybody fixed androdi gyroscope script on 3.5.6? It don't work !!!

    From the changelog:

    Android: Gyro.attitude did not compensate for screen orientation, nor device natural orientation (phone/tablet) - this has been fixed.

    Thanks
     
  10. kaz2057

    kaz2057

    Joined:
    Jan 18, 2011
    Posts:
    326
    UP

     
  11. shinichi88

    shinichi88

    Joined:
    May 4, 2011
    Posts:
    80
    "The Unity mobile devices input API is based on Apple's iOS API." (Unity/Editor/Data/Documentation/Documentation/ScriptReference/Input.html)
    Ultimately, I tested this on Unity 3.5.6f4, the setting for Android should be the same as iOS.
    Code (csharp):
    1.  
    2. camParent.transform.eulerAngles = Vector3(90,90,0);
    3.            
    4. if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    5.    quatMult = Quaternion(0,0,1,0); //**
    6. } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    7.    quatMult = Quaternion(0,0,1,0); //**
    8. } else if (Screen.orientation == ScreenOrientation.Portrait) {
    9.    quatMult = Quaternion(0,0,1,0); //**
    10. } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    11.    quatMult = Quaternion(0,0,0,1); // Unable to build package on upsidedown
    12. }
    13.  
    Using gyro.Attitude quaternion xyzw
    Code (csharp):
    1.  
    2. quatMap = gyro.attitude;
    3.  
    OR
    Code (csharp):
    1.  
    2. quatMap = Quaternion(gyro.attitude.x,gyro.attitude.y,gyro.attitude.z,gyro.attitude.w);
    3.  
    **Updates : All Screen Orientation use the same quatMult value.Not sure if this setting apply on iOS
    Code (csharp):
    1.  
    2. quatMult = Quaternion(0,0,1,0);
    3.  
    Personally, I tried this script on Asus Transformer Prime TF201, and Samsung Galaxy Note...
    Both using the same script and work perfectly.
     
    Last edited: Oct 23, 2012
  12. kaz2057

    kaz2057

    Joined:
    Jan 18, 2011
    Posts:
    326
    Thanks shinichi88. You are my rescuer!!

    I don't know what was wrong when, last week, I tried to modify the base script with your same value, but i didn't work.

    With your setup now everything works correctly.

    Thanks
     
  13. shinichi88

    shinichi88

    Joined:
    May 4, 2011
    Posts:
    80
    You must be using the old version I've post before the latest update, that come with those 0.707 values. (Current : Quaternion(0,0,1,0) )
    I'm not pretty sure on this settings, but it just work. No idea what's Unity changes from previous with just a few words in changelog.
    Unity should update script reference with example codes in order to get it work correctly.

    There something bothering me about the gyro value. It seems to drift around and it makes the camera "auto rotate" and not precise.
    Not sure which side having problem. Unity API or Hardware?
     
  14. digiben

    digiben

    Joined:
    Aug 18, 2012
    Posts:
    7
    After days and probably over 20 hours of researching and coding and testing to try and find out why the heck I couldn't get the gyroscope to orient correctly, I found this code and it works flawlessly. All the contributors on this are my heros and I am VERY grateful for the time taken to post this code and example.
     
  15. Voxel85

    Voxel85

    Joined:
    Sep 26, 2012
    Posts:
    2
    Can you help me? I use your script in my project. It is a project for my iPhone. It worked perfectly. Since Unity 4, it no longer works. I do not understand the problem. I changed gyroBool = Input.isGyroAvailable; with gyroBool= SystemInfo.supportsGyroscope;. I switched because of this warning:
    WARNING: 'UnityEngine.Input.isGyroAvailable' is obsolete. isGyroAvailable property is deprecated. Please use SystemInfo.supportsGyroscope instead.

    I would be very happy if you could help me.
     
  16. reganmusic

    reganmusic

    Joined:
    Apr 6, 2012
    Posts:
    7
    thanks!!!! you rule!!!!
     
    Last edited: Dec 11, 2012
  17. Seppel

    Seppel

    Joined:
    Jan 7, 2013
    Posts:
    1
    Hello there guys,

    i´m trying to get the gyroscript to work.

    I´m using Unity4pro and an Android Samsung Galaxy S3.
    I´ve changed the Script like shinchi88 already said.
    And now unsing this Script on my MainCamera, but it doesnt work.
    The App is staring but the Camera dont moves by the Gyrodatas.

    Could you please help me?
    Thank You


    Code (csharp):
    1. #pragma strict
    2.     // Gyroscope-controlled camera for iPhone  Android revised 2.26.12
    3.     // Perry Hoberman <hoberman@bway.net>
    4.     //
    5.     // Usage:
    6.     // Attach this script to main camera.
    7.     // Note: Unity Remote does not currently support gyroscope.
    8.     //
    9.     // This script uses three techniques to get the correct orientation out of the gyroscope attitude:
    10.     // 1. creates a parent transform (camParent) and rotates it with eulerAngles
    11.     // 2. for Android (Samsung Galaxy Nexus) only: remaps gyro.Attitude quaternion values from xyzw to wxyz (quatMap)
    12.     // 3. multiplies attitude quaternion by quaternion quatMult
    13.      
    14.     // Also creates a grandparent (camGrandparent) which can be rotated with localEulerAngles.y
    15.     // This node allows an arbitrary heading to be added to the gyroscope reading
    16.     // so that the virtual camera can be facing any direction in the scene, no matter what the phone's heading
    17.      
    18.     static var gyroBool : boolean;
    19.     private var gyro : Gyroscope;
    20.     private var quatMult : Quaternion;
    21.     private var quatMap : Quaternion;
    22.      
    23.     function Awake() {
    24.         // find the current parent of the camera's transform
    25.         var currentParent = transform.parent;
    26.         // instantiate a new transform
    27.         var camParent = new GameObject ("camParent");
    28.         // match the transform to the camera position
    29.         camParent.transform.position = transform.position;
    30.         // make the new transform the parent of the camera transform
    31.         transform.parent = camParent.transform;
    32.         // make the original parent the grandparent of the camera transform
    33.         //camParent.transform.parent = currentParent;
    34.         // instantiate a new transform
    35.         var camGrandparent = new GameObject ("camGrandParent");
    36.         // match the transform to the camera position
    37.         camGrandparent.transform.position = transform.position;
    38.         // make the new transform the parent of the camera transform
    39.         camParent.transform.parent = camGrandparent.transform;
    40.         // make the original parent the grandparent of the camera transform
    41.         camGrandparent.transform.parent = currentParent;
    42.            
    43.         // check whether device supports gyroscope
    44.         #if UNITY_3_4
    45.         gyroBool = Input.isGyroAvailable;
    46.         #endif
    47.         #if UNITY_3_5
    48.         gyroBool = SystemInfo.supportsGyroscope;
    49.         #endif
    50.        
    51.         if (gyroBool) {
    52.             gyro = Input.gyro;
    53.             gyro.enabled = true;
    54.             #if UNITY_IPHONE
    55.                     camParent.transform.eulerAngles = Vector3(90,90,0);
    56.                
    57.                         if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    58.                            quatMult = Quaternion(0,0,1,0); //**
    59.                         } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    60.                            quatMult = Quaternion(0,0,1,0); //**
    61.                         } else if (Screen.orientation == ScreenOrientation.Portrait) {
    62.                            quatMult = Quaternion(0,0,1,0); //**
    63.                         } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    64.                            quatMult = Quaternion(0,0,1,0); // Unable to build package on upsidedown
    65.                         }
    66.             #endif
    67.             #if UNITY_ANDROID
    68.                     camParent.transform.eulerAngles = Vector3(90,90,0);
    69.                
    70.                         if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    71.                            quatMult = Quaternion(0,0,1,0); //**
    72.                         } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    73.                            quatMult = Quaternion(0,0,1,0); //**
    74.                         } else if (Screen.orientation == ScreenOrientation.Portrait) {
    75.                            quatMult = Quaternion(0,0,1,0); //**
    76.                         } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    77.                            quatMult = Quaternion(0,0,1,0); // Unable to build package on upsidedown
    78.                         }
    79.             #endif
    80.             Screen.sleepTimeout = SleepTimeout.NeverSleep;
    81.         } else {
    82.             #if UNITY_EDITOR
    83.                 //print("NO GYRO");
    84.             #endif
    85.         }
    86.     }
    87.      
    88.     function Update () {
    89.         if (gyroBool) {
    90.             #if UNITY_IPHONE
    91.                 quatMap = gyro.attitude;
    92.             #endif
    93.             #if UNITY_ANDROID
    94.                 quatMap = Quaternion(gyro.attitude.x,gyro.attitude.y,gyro.attitude.z,gyro.attitude.w);
    95.             #endif
    96.             transform.localRotation = quatMap * quatMult;
    97.         }
    98.     }
     
    Last edited: Jan 7, 2013
  18. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    what's the updated quatMult for Unity 3.5.7?
     
  19. Wiggitamoo

    Wiggitamoo

    Joined:
    Jan 16, 2013
    Posts:
    1
    Really nice work. Worked like a charm!
     
  20. charmandermon

    charmandermon

    Joined:
    Dec 4, 2011
    Posts:
    352
    Ive updated the code so it works with Unity 4 :)

    Code (csharp):
    1. #pragma strict
    2.  
    3.     // Gyroscope-controlled camera for iPhone  Android revised 2.26.12
    4.  
    5.     // Perry Hoberman <hoberman@bway.net>
    6.  
    7.     //
    8.  
    9.     // Usage:
    10.  
    11.     // Attach this script to main camera.
    12.  
    13.     // Note: Unity Remote does not currently support gyroscope.
    14.  
    15.     //
    16.  
    17.     // This script uses three techniques to get the correct orientation out of the gyroscope attitude:
    18.  
    19.     // 1. creates a parent transform (camParent) and rotates it with eulerAngles
    20.  
    21.     // 2. for Android (Samsung Galaxy Nexus) only: remaps gyro.Attitude quaternion values from xyzw to wxyz (quatMap)
    22.  
    23.     // 3. multiplies attitude quaternion by quaternion quatMult
    24.  
    25.      
    26.  
    27.     // Also creates a grandparent (camGrandparent) which can be rotated with localEulerAngles.y
    28.  
    29.     // This node allows an arbitrary heading to be added to the gyroscope reading
    30.  
    31.     // so that the virtual camera can be facing any direction in the scene, no matter what the phone's heading
    32.  
    33.      
    34.  
    35.     static var gyroBool : boolean;
    36.  
    37.     private var gyro : Gyroscope;
    38.  
    39.     private var quatMult : Quaternion;
    40.  
    41.     private var quatMap : Quaternion;
    42.  
    43.      
    44.  
    45.     function Awake() {
    46.  
    47.         // find the current parent of the camera's transform
    48.  
    49.         var currentParent = transform.parent;
    50.  
    51.         // instantiate a new transform
    52.  
    53.         var camParent = new GameObject ("camParent");
    54.  
    55.         // match the transform to the camera position
    56.  
    57.         camParent.transform.position = transform.position;
    58.  
    59.         // make the new transform the parent of the camera transform
    60.  
    61.         transform.parent = camParent.transform;
    62.  
    63.         // make the original parent the grandparent of the camera transform
    64.  
    65.         //camParent.transform.parent = currentParent;
    66.  
    67.         // instantiate a new transform
    68.  
    69.         var camGrandparent = new GameObject ("camGrandParent");
    70.  
    71.         // match the transform to the camera position
    72.  
    73.         camGrandparent.transform.position = transform.position;
    74.  
    75.         // make the new transform the parent of the camera transform
    76.  
    77.         camParent.transform.parent = camGrandparent.transform;
    78.  
    79.         // make the original parent the grandparent of the camera transform
    80.  
    81.         camGrandparent.transform.parent = currentParent;
    82.  
    83.            
    84.  
    85.         // check whether device supports gyroscope
    86.  
    87.  
    88.        //Removed Unity version Checks to support unity 4 - dustin.hagen
    89.         gyroBool = SystemInfo.supportsGyroscope;
    90.  
    91.  
    92.  
    93.        
    94.  
    95.         if (gyroBool) {
    96.  
    97.             gyro = Input.gyro;
    98.  
    99.             gyro.enabled = true;
    100.  
    101.             #if UNITY_IPHONE
    102.  
    103.                     camParent.transform.eulerAngles = Vector3(90,90,0);
    104.  
    105.                
    106.  
    107.                         if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    108.  
    109.                            quatMult = Quaternion(0,0,1,0); //**
    110.  
    111.                         } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    112.  
    113.                            quatMult = Quaternion(0,0,1,0); //**
    114.  
    115.                         } else if (Screen.orientation == ScreenOrientation.Portrait) {
    116.  
    117.                            quatMult = Quaternion(0,0,1,0); //**
    118.  
    119.                         } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    120.  
    121.                            quatMult = Quaternion(0,0,1,0); // Unable to build package on upsidedown
    122.  
    123.                         }
    124.  
    125.             #endif
    126.  
    127.             #if UNITY_ANDROID
    128.  
    129.                     camParent.transform.eulerAngles = Vector3(90,90,0);
    130.  
    131.                
    132.  
    133.                         if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    134.  
    135.                            quatMult = Quaternion(0,0,1,0); //**
    136.  
    137.                         } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    138.  
    139.                            quatMult = Quaternion(0,0,1,0); //**
    140.  
    141.                         } else if (Screen.orientation == ScreenOrientation.Portrait) {
    142.  
    143.                            quatMult = Quaternion(0,0,1,0); //**
    144.  
    145.                         } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    146.  
    147.                            quatMult = Quaternion(0,0,1,0); // Unable to build package on upsidedown
    148.  
    149.                         }
    150.  
    151.             #endif
    152.  
    153.             Screen.sleepTimeout = SleepTimeout.NeverSleep;
    154.  
    155.         } else {
    156.  
    157.             #if UNITY_EDITOR
    158.  
    159.                 //print("NO GYRO");
    160.  
    161.             #endif
    162.  
    163.         }
    164.  
    165.     }
    166.  
    167.      
    168.  
    169.     function Update () {
    170.  
    171.         if (gyroBool) {
    172.  
    173.             #if UNITY_IPHONE
    174.  
    175.                 quatMap = gyro.attitude;
    176.  
    177.             #endif
    178.  
    179.             #if UNITY_ANDROID
    180.  
    181.                 quatMap = Quaternion(gyro.attitude.x,gyro.attitude.y,gyro.attitude.z,gyro.attitude.w);
    182.  
    183.             #endif
    184.  
    185.             transform.localRotation = quatMap * quatMult;
    186.  
    187.         }
    188.  
    189.     }
     
  21. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    Aren't Android and iPhone code paths the same now? :)
     
  22. Utopya

    Utopya

    Joined:
    Jan 31, 2013
    Posts:
    2
    How about devices without gyro? Is there anybody who can give me some tips to write someting that works with accelerometer and compass?
     
  23. jhybe

    jhybe

    Joined:
    Feb 3, 2013
    Posts:
    13
    Thanks for this script
    works great on iPad 2.

    Just an issue to move the player using the characters prefab.

    If I put the script onto my camera, it moves according to my iPad, but the character don't rotate.
    So, I puted the script directly onto the character, but when I rotate the iPad, the capsule rotate also.. so the height of the camera is not always the same.

    How can I do? Do I have to put the script on my camera, and make another script so that when I rotate the capsule rotate as well?

    Thanks, Jonathan
     
  24. KareemErgawy

    KareemErgawy

    Joined:
    Jan 11, 2013
    Posts:
    8
    Great Work, I used it on my Android device and it worked perfectly.
     
  25. charmandermon

    charmandermon

    Joined:
    Dec 4, 2011
    Posts:
    352
    Can anyone help figure how to do a proper gyro orientation calibration. Turning the gyro off then on again doesn't reset it anymore since the latest 2 unity builds.

    Any help would be greatly appreciated the math is beyond my skills. To be clear I'm looking for a way to calibrate the camera so it works while a person is laying down then if they stand up and move positions they press calibrate and it readjusts the cameras orientation. Also I am not referring to actual device orientation (landscape, portrait).
     
    Last edited: Mar 19, 2013
  26. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    Unity 4.1 should fix gyro restart problem.
     
  27. charmandermon

    charmandermon

    Joined:
    Dec 4, 2011
    Posts:
    352
    Thanks mantas for the quick reply.
    I read through the release notes and it doesn't mention it anywhere. Also the gyro reset (turning it off and on) was more of a hack and only calibrates one of the axis' not all 3. Honestly a better solution is to add a calibration formula. Anyone have any ideas on how to do it? Thanks!
     
  28. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    Sorry my bad. It is scheduled for 4.2.
     
  29. QingRuoChen

    QingRuoChen

    Joined:
    Jan 17, 2013
    Posts:
    4
    Thank you~!
     
  30. leonida

    leonida

    Joined:
    Jul 3, 2012
    Posts:
    2
    thanks!
    can someone post a sample scene where he uses the correct script for unity4?
    I tried it on Android but the view does not follow the gyroscope.

    how to calculate rotation of axis in ScreenOrientation.LandscapeLeft??
     
    Last edited: Apr 15, 2013
  31. Nooch

    Nooch

    Joined:
    Dec 31, 2011
    Posts:
    18
    Thanks so much for this script, phoberman! :cool:
    Fantastic stuff!! (Yeah I know I'm 2 years late).

    I wanted to share a small modification I did, in order to fix the issue of camera stuttering.
    On iPad2, I noticed every 1-2 seconds the camera stutters while rotating (not sure about other devices).
    This script isn't causing the problem, it's something with Unity itself. Perhaps this was fixed in later versions, I'm not sure (on 3.5.7 here).

    That said, we can apply a small change here in order to fix it:

    Code (csharp):
    1.  
    2. var currentRot : Quaternion;
    3. var newRot : Quaternion;
    4. var smoothingAmount : float = 10;
    5.  
    6. ...
    7.  
    8. function Update()
    9. {
    10.     if (gyroBool)
    11.     {
    12.         // Get current rotation
    13.         currentRot = transform.localRotation;
    14.    
    15.         ... (existing code) ...
    16.        
    17.         // Get new rotation, apply smoothed result to camera
    18.         newRot = quatMap * quatMult;
    19.         transform.localRotation = Quaternion.Lerp(currentRot, newRot, Time.smoothDeltaTime * smoothingAmount);
    20.     }
    21. }
    22.  
    This smooths the rotation and eliminates the stutters. This does introduce a tiny amount of lag, but I think it's acceptable, and results overall look nicer. You can adjust this by tweaking the smoothingAmount value. A lower number will smooth over a longer period. A higher number will be quicker, but if you get too high (like 20 or so), you'll start to see stuttering again. So feel free to try it for yourself and find a nice value. It works well for me, but YMMV of course. :)
     
  32. aroha

    aroha

    Joined:
    Jan 8, 2013
    Posts:
    18
    Following script ported to C#, tested for all 4 orientations on Unity 4.1, Android and iOS.
    Android: Galaxy S3 4.1.1, Sony Xperia 4.0.4, ASUS TF101 Tablet 4.0.3
    iOS: iPad2 and iPhone5

    Update: I realized that the Android orientations were correct but the "direction" wasn't. It was just by chance the direction I was sitting at my desk aligned with the gyroscope when I first opened the Unity scene. Unlike my tests on my iOS devices, the "front" of the scene did not automatically adjust itself to the direction the phone was pointing when I opened my scene. I updated the script below to Perry's latest script from page 4 that supposedly fixes this issue with using a grandparent game object but that didn't work on my Galaxy S3. I updated the code below to use a scroll bar so you can manually adjust the Y axis rotation to get the right direction.

    Code (csharp):
    1. // Gyroscope-controlled camera for iPhone  Android revised 2.26.12
    2. // Perry Hoberman <hoberman@bway.net>
    3. //
    4. // Usage:
    5. // Attach this script to main camera.
    6. // Note: Unity Remote does not currently support gyroscope.
    7. //
    8. // This script uses three techniques to get the correct orientation out of the gyroscope attitude:
    9. // 1. creates a parent transform (camParent) and rotates it with eulerAngles
    10. // 2. for Android (Samsung Galaxy Nexus) only: remaps gyro.Attitude quaternion values from xyzw to wxyz (quatMap)
    11. // 3. multiplies attitude quaternion by quaternion quatMult
    12. // Also creates a grandparent (camGrandparent) which can be rotated with localEulerAngles.y
    13. // This node allows an arbitrary heading to be added to the gyroscope reading
    14. // so that the virtual camera can be facing any direction in the scene, no matter what the phone's heading
    15. //
    16. // Ported to C# by Simon McCorkindale <simon <at> aroha.mobi>
    17.  
    18. using UnityEngine;
    19.  
    20. public class GyroCam : MonoBehaviour
    21. {
    22.     private bool gyroBool;
    23.     private Gyroscope gyro;
    24.     private Quaternion rotFix;
    25.  
    26.     public void Start ()
    27.     {
    28.         Transform currentParent = transform.parent;
    29.         GameObject camParent = new GameObject ("GyroCamParent");
    30.         camParent.transform.position = transform.position;
    31.         transform.parent = camParent.transform;
    32.         GameObject camGrandparent = new GameObject ("GyroCamGrandParent");
    33.         camGrandparent.transform.position = transform.position;
    34.         camParent.transform.parent = camGrandparent.transform;
    35.         camGrandparent.transform.parent = currentParent;
    36.  
    37.         #if UNITY_3_4
    38.         gyroBool = Input.isGyroAvailable;
    39.         #else
    40.         gyroBool = SystemInfo.supportsGyroscope;
    41.         #endif
    42.    
    43.         if (gyroBool) {
    44.          
    45.             gyro = Input.gyro;
    46.             gyro.enabled = true;
    47.          
    48.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    49.                 camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
    50.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    51.                 camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
    52.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    53.                 camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
    54.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    55.                 camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
    56.             } else {
    57.                 camParent.transform.eulerAngles = new Vector3 (90, 180, 0);
    58.             }
    59.  
    60.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    61.                 rotFix = new Quaternion (0, 0, 1, 0);
    62.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    63.                 rotFix = new Quaternion (0, 0, 1, 0);
    64.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    65.                 rotFix = new Quaternion (0, 0, 1, 0);
    66.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    67.                 rotFix = new Quaternion (0, 0, 1, 0);
    68.             } else {
    69.                 rotFix = new Quaternion (0, 0, 1, 0);
    70.             }
    71.  
    72.             //Screen.sleepTimeout = 0;
    73.         } else {
    74.             #if UNITY_EDITOR
    75.             print("NO GYRO");
    76.             #endif
    77.         }
    78.     }
    79.    
    80.     public void Update ()
    81.     {
    82.         if (gyroBool  this.gameObject.camera.enabled) {
    83.             Quaternion quatMap;
    84.             #if UNITY_IPHONE
    85.                 quatMap = gyro.attitude;
    86.             #elif UNITY_ANDROID
    87.                 quatMap = new Quaternion(gyro.attitude.x,gyro.attitude.y,gyro.attitude.z,gyro.attitude.w);
    88.             #endif
    89.             transform.localRotation = quatMap * rotFix;
    90.         }
    91.     }
    92.  
    93.     float scroll = 180f;
    94.  
    95.     public void OnGUI ()
    96.     {
    97.         if (gyroBool  this.gameObject.camera.enabled) {
    98.             // Add scrollbar to rotate around Y axis 0-360 for manual adjustment
    99.             scroll = GUI.VerticalScrollbar (new Rect (Screen.width - 35, 25, 30, Screen.height / 2), scroll, 1.0f, 0.0f, 360.0f);
    100.         }
    101.         if (GUI.changed) {
    102.             transform.parent.eulerAngles = new Vector3 (transform.parent.eulerAngles.x, scroll, transform.parent.eulerAngles.z);
    103.         }
    104.     }
    105. }
    106.  
     
    Last edited: May 5, 2013
  33. BooBi

    BooBi

    Joined:
    Jan 18, 2010
    Posts:
    534
    Does anyone managed to link it to the FPS Controller?
    I would like to use it for my camera and use the left joystick to move forward, I can't manage to link the rotation X of the camera to my FPS Controller. I should probably split the script in two scripts one managing the Yaw for the fps controller and the other managing the pitch and roll for the camera. I don't get how to manage that by playing with the quaternions without being too extensive on the performances...

    Any help would be much appreciated!
    Thanks in advance
     
    Last edited: May 14, 2013
  34. RebelFuture

    RebelFuture

    Joined:
    Nov 28, 2012
    Posts:
    7

    This was VERY helpful for me. Thank you. Below I am posting the code I wrote after learning from your post. This class moves the camera Left, Right, Up, Down based upon the gyro.rotationRate. While moving the camera keeps itself focused on it's target. This makes for some interesting movement when viewing a 2D UI in perspective mode.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GyroCameraControl : IgnoreTimeScale
    5. {
    6.     private bool gyroBool;
    7.     private Gyroscope gyro;
    8.    
    9.     private Transform mTrans;
    10.     private Vector2 mRot = Vector2.zero;
    11.    
    12.     // the camera will continue to look at this as it moves, keep it in perspective mode
    13.     public GameObject cameraTarget;
    14.    
    15.     void Start()
    16.     {
    17.         gyroBool = SystemInfo.supportsGyroscope;
    18.        
    19.         if ( gyroBool ) {
    20.            
    21.             mTrans = transform;
    22.            
    23.             gyro = Input.gyro;
    24.             gyro.enabled = true;
    25.         } else {
    26.             print( "NO GYRO" );
    27.         }
    28.     }
    29.  
    30.     void Update ()
    31.     {
    32.         if (gyroBool) {
    33.             float delta = UpdateRealTimeDelta();
    34.            
    35.             mRot = Vector2.Lerp(mRot, new Vector2( Input.gyro.rotationRate.y, Input.gyro.rotationRate.x ), delta * 5f);
    36.    
    37.             transform.localPosition = new Vector3( mRot.x*10f, mRot.y*10f, mTrans.localPosition.z );
    38.             transform.LookAt( cameraTarget.transform.position );
    39.         }
    40.     }
    41. }
     
  35. Budgieboy

    Budgieboy

    Joined:
    Sep 6, 2012
    Posts:
    39
    This doesn't work for me, what do I need to do?

    I'm trying to create a moving gyro camera with boundaries and I've tried scrips all over Google with hardly even close success and I've spent days, please someone help me! :(
     
  36. Siusega

    Siusega

    Joined:
    Mar 5, 2013
    Posts:
    7
    Works on Asus Transformer!. After 7 hours of trying to fix the first version. Thanks!
     
  37. Sanky

    Sanky

    Joined:
    Jan 16, 2013
    Posts:
    3
    hey phoberman i want know that is this script works with android device because i am trying to do this on android device.
     
  38. sorushe-mehre

    sorushe-mehre

    Joined:
    Aug 12, 2013
    Posts:
    8
    i test this script and work good on many android devices but does not work on android 4.2!!!
    any one has similar problem?
    any one can help to solve this issue
     
  39. Loyalwater

    Loyalwater

    Joined:
    Nov 1, 2013
    Posts:
    7
    Hi Everyone !!

    One quick question ... hope some kind soul would help .. How can we invert the roll? When the phone turns clockwise, the gyro turns anti clockwise and vice versa. Left Right Up n DOwn are working perfectly fine. I know that the roll behavior I want to reverse is the normal behavior. I have seen it in gyro enabled games. But I want to reverse it. Can some one please help me with the math here. What do I need to change?
     
  40. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    Thanks to aroha for sharing your script, works really good! I get an intial offset on the camera though (seems to be rotated/moved 90 degrees off to the side on my ipad) I had to hardcode the initial offset for this to work on my ipad, any idea on how to make a better universal solution?
     
  41. franktinsley

    franktinsley

    Joined:
    Jul 1, 2010
    Posts:
    130
  42. dsimoes12

    dsimoes12

    Joined:
    Apr 16, 2014
    Posts:
    15
    Hello everyone,

    I've tried 3 or 4 gyro camera scripts in the last few weeks but none of them really satisfied me completely. I would fix them myself but there are some details I dont quite understand.

    One of the bugs that is really annoying me is when I start the game, the camera always smoothly rotates about 90 degrees to the right (on Y)! Has anyone experienced this before? Is there a way to force a calibration of the gyro so that when the game starts thr camera is facing the way it is facing on the editor?

    Using Unity 4.3, developing for Android and testing on Nexus 5.

    thanks
     
    Last edited: May 1, 2014
  43. anivader1789

    anivader1789

    Joined:
    Sep 3, 2013
    Posts:
    2
    Works well. Thanks for sharing!!
     
  44. ostinelli

    ostinelli

    Joined:
    Apr 7, 2014
    Posts:
    2
    I'm trying to align the scene with the Compass' north. To do so, I set in the Update() function:

    Code (JavaScript):
    1. camGrandparent.transform.localEulerAngles.y = Input.compass.trueHeading;
    For debugging purposes, I print on the screen the value of Input.compass.trueHeading.

    I rotate the device until 0 is printed out (i.e. the device is heading north), however the scene is actually not aligned with it (I have a cube at position 0, 0, 100 and it is not in the middle of the screen when the device is heading north). Its position actually varies: to have the cube in the center of the screen I need to rotate the device until Input.compass.trueHeading is something like 40, for instance.

    Moreover, if I turn the device 180 around (i.e. Input.compass.trueHeading is 220), I see the cube again! (I only have 1 cube in the scene).

    Can anyone give me hints on what I might be doing wrong? I've been going nuts on this one and I hope some kind soul can help me out here.

    I'm using an iOS device in Landscape Left only orientation.

    Thank you,
    r.

    PS: using Unity 4.5.2.

    The complete code is:
    Code (JavaScript):
    1. #pragma strict
    2.  
    3. static var gyroBool : boolean;
    4. private var gyro : Gyroscope;
    5. private var quatMult : Quaternion;
    6. private var quatMap : Quaternion;
    7. private var camGrandparent : GameObject;
    8. function Awake() {
    9.     // find the current parent of the camera's transform
    10.     var currentParent : Transform = transform.parent;
    11.     // instantiate a new transform
    12.     var camParent : GameObject = new GameObject("camParent");
    13.     // match the transform to the camera position
    14.     camParent.transform.position = transform.position;
    15.     // make the new transform the parent of the camera transform
    16.     transform.parent = camParent.transform;
    17.  
    18.     // Also creates a grandparent (camGrandparent) which can be rotated with localEulerAngles.y
    19.     // This node allows an arbitrary heading to be added to the gyroscope reading
    20.     // so that the virtual camera can be facing any direction in the scene, no matter what the phone's heading
    21.     camGrandparent = new GameObject("camGrandParent");
    22.     // match the transform to the camera position
    23.     camGrandparent.transform.position = transform.position;
    24.     // make the new transform the parent of the camera transform
    25.     camParent.transform.parent = camGrandparent.transform;
    26.     // make the original parent the grandparent of the camera transform
    27.     camGrandparent.transform.parent = currentParent;
    28.  
    29.     // check whether device supports gyroscope
    30.     gyroBool = SystemInfo.supportsGyroscope;
    31.  
    32.     if (gyroBool) {
    33.         gyro = Input.gyro;
    34.         gyro.enabled = true;
    35.      
    36.         #if UNITY_IPHONE
    37.             camParent.transform.eulerAngles = Vector3(90, 90, 0);
    38.             quatMult = Quaternion(0, 0, 1, 0);
    39.         #endif
    40.      
    41.         Screen.sleepTimeout = SleepTimeout.NeverSleep;
    42.     } else {
    43.         print("NO GYRO");
    44.     }
    45. }
    46.  
    47. function Start() {
    48.     // First, check if user has location service enabled
    49.     if (!Input.location.isEnabledByUser)
    50.         return;
    51.  
    52.     // Start service before querying location
    53.     Input.location.Start();
    54.     Input.compass.enabled = true;
    55.  
    56.     // Wait until service initializes
    57.     var maxWait : int = 20;
    58.     while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0) {
    59.         yield WaitForSeconds(1);
    60.         maxWait--;
    61.     }
    62.  
    63.     if (maxWait < 1) {
    64.         // Service didn't initialize in 20 seconds
    65.         print("Timed out");
    66.         return;
    67.     }
    68.  
    69.     if (Input.location.status == LocationServiceStatus.Failed) {
    70.         // Connection has failed
    71.         print("Unable to determine device location");
    72.         return;
    73.     }
    74. }
    75. function Update() {
    76.     if (gyroBool) {
    77.         #if UNITY_IPHONE
    78.             quatMap = gyro.attitude;
    79.         #endif
    80.      
    81.         camGrandparent.transform.localEulerAngles.y = Input.compass.trueHeading;
    82.         transform.localRotation = quatMap * quatMult;
    83.     }
    84. }
    85.  
     
    Last edited: Aug 5, 2014
  45. VioletteA

    VioletteA

    Joined:
    Sep 19, 2014
    Posts:
    2

    Hi Dsimoes12, i had the same problem... You can change the camRot, it seems to work:

    var camRot: Quaternion = gyro.attitude * rotFix * Quaternion.Euler (0,0,90);

    But i think that it remains a problem with the calibration of gyros ...
     
  46. Palve

    Palve

    Joined:
    Aug 28, 2015
    Posts:
    2
    How to move camera with player on ios device
     
  47. Palve

    Palve

    Joined:
    Aug 28, 2015
    Posts:
    2
    privatevoidFixedUpdate()
    {
    GroundCheck();
    Vector2input = GetInput();

    if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon) && (advancedSettings.airControl || m_IsGrounded))
    {
    //alwaysmovealongthecameraforwardasitisthedirectionthatitbeingaimedat
    Vector3desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;
    desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;

    desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;
    desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;
    desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;
    if (m_RigidBody.velocity.sqrMagnitude <
    (movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed))
    {
    m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);
    }
    }

    if (m_IsGrounded)
    {
    m_RigidBody.drag = 5f;

    if (m_Jump)
    {
    m_RigidBody.drag = 0f;
    m_RigidBody.velocity = newVector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);
    m_RigidBody.AddForce(newVector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);
    m_Jumping = true;
    }

    if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
    {
    m_RigidBody.Sleep();
    }
    }
    else
    {
    m_RigidBody.drag = 0f;
    if (m_PreviouslyGrounded && !m_Jumping)
    {
    StickToGroundHelper();
    }
    }
    m_Jump = false;
    }



    Above script is working on MAC but not working on device
     
  48. Bellerion

    Bellerion

    Joined:
    Jan 9, 2016
    Posts:
    1
    Hello, i'm new on the forum and just discovered your script, its simply AMAZING !!!

    I love it, i was trying to do the same with acceleration and gyro but couldnt make it alone... seems i'm not a good develloper enough :D

    The fact is, i use unity remote and i am trying to use this code for an ipad app

    some fun thing :

    1) the code should not work with remote (or so i saw in previous post) well, it work with me :) i use remote 4 and it support this code it seems, works perfectly with my ipad so i was happy

    2) when i use unity to export the project to xcode, everything seems good, no error, i build it aaaaaaand it dont work :S

    Dont know why but i tried the multiple code given (old and newest) old one freeze on the front z+ it seems but new one freeze on the ground y- ...

    so i guessed the old one was simply not updating or something while the new one update once or maybe just start on y-...

    Not sure about it, i didnt change anything in the code but i would love to know if someone experienced something similiar.. it kill me ! i was sure it would work since with remote it worked perfectly :S

    Thx by advance for your answer and comment.

    cya !
     
  49. luckey179

    luckey179

    Joined:
    Mar 10, 2016
    Posts:
    11
    Okay so when I use my script, everything works perfectly fine, but it moves up and slightly to the right constantly. Is this the Earths rotation having an effect on the gyropscope? How do I get it to stay still when not moving? Thanks
     
  50. ulissescad

    ulissescad

    Joined:
    Oct 31, 2015
    Posts:
    14
    Works on unity 5.3.5f1 and android 6. The same code making people happy since 2012! Thanks probleman.


    using UnityEngine;
    /// <summary>
    /// Gyroscope demo. Attach to a visible object or camera.
    /// </summary>
    public class GyroTest : MonoBehaviour
    {

    #pragma strict
    // Gyroscope-controlled camera for iPhone Android revised 2.26.12
    // Stereoskopix FOV2GO Copyright (c) 2011 Perry Hoberman
    // Perry Hoberman <hoberman@bway.net>
    //
    // Usage:
    // Attach this script to main camera.
    // Note: Unity Remote does not currently support gyroscope.
    // Use Landscape Left for correct orientation
    //
    // This script uses three techniques to get the correct orientation out of the gyroscope attitude:
    // 1. creates a parent transform (camParent) and rotates it with eulerAngles
    // 2. for Android (Samsung Galaxy Nexus) only: remaps gyro.Attitude quaternion values from xyzw to wxyz (quatMap)
    // 3. multiplies attitude quaternion by quaternion quatMult

    // Also creates a grandparent (camGrandparent) which can be rotated to change heading
    // This node allows an arbitrary heading to be added to the gyroscope reading
    // so that the virtual camera can be facing any direction in the scene, no matter which way the phone is actually facing
    // Option for touch input - horizontal swipe controls heading

    static bool gyroBool ;
    private Gyroscope gyro;
    private Quaternion quatMult;
    private Quaternion quatMap;
    // camera grandparent node to rotate heading
    private GameObject camGrandparent;
    private float heading = 0;

    // mouse/touch input
    public bool touchRotatesHeading = true;
    private Vector2 screenSize;
    private Vector2 mouseStartPoint;
    private float headingAtTouchStart = 0;
    //@script AddComponentMenu("stereoskopix/s3d Gyro Cam")

    void Awake()
    {
    // find the current parent of the camera's transform
    var currentParent = transform.parent;
    // instantiate a new transform
    var camParent = new GameObject("camParent");
    // match the transform to the camera position
    camParent.transform.position = transform.position;
    // make the new transform the parent of the camera transform
    transform.parent = camParent.transform;
    // instantiate a new transform
    camGrandparent = new GameObject("camGrandParent");
    // match the transform to the camera position
    camGrandparent.transform.position = transform.position;
    // make the new transform the grandparent of the camera transform
    camParent.transform.parent = camGrandparent.transform;
    // make the original parent the great grandparent of the camera transform
    camGrandparent.transform.parent = currentParent;

    // check whether device supports gyroscope
    #if UNITY_3_4
    gyroBool = Input.isGyroAvailable;
    #endif
    #if UNITY_3_5
    gyroBool = SystemInfo.supportsGyroscope;
    #endif

    gyro = Input.gyro;
    gyro.enabled = true;
    #if UNITY_IPHONE
    camParent.transform.eulerAngles = Vector3(90,90,0);
    if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    quatMult = Quaternion(0,0,0.7071,0.7071);
    } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    quatMult = Quaternion(0,0,-0.7071,0.7071);
    } else if (Screen.orientation == ScreenOrientation.Portrait) {
    quatMult = Quaternion(0,0,1,0);
    } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    quatMult = Quaternion(0,0,0,1);
    }
    #endif
    #if UNITY_ANDROID
    camParent.transform.eulerAngles = new Vector3(180, 0, 0);
    if (Screen.orientation == ScreenOrientation.LandscapeLeft)
    {
    quatMult =new Quaternion(0, 0, 0.7071f, -0.7071f);
    }
    else if (Screen.orientation == ScreenOrientation.LandscapeRight)
    {
    quatMult = new Quaternion(0, 0, -0.7071f, -0.7071f);
    }
    else if (Screen.orientation == ScreenOrientation.Portrait)
    {
    quatMult = new Quaternion(0, 0, 0, 1);
    }
    else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)
    {
    quatMult = new Quaternion(0, 0, 1, 0);
    }
    #endif
    Screen.sleepTimeout = SleepTimeout.NeverSleep;

    }

    void Start()
    {
    screenSize.x = Screen.width;
    screenSize.y = Screen.height;

    Input.gyro.enabled = true;
    Input.location.Start(5, 5);
    }

    void Update()
    {


    #if UNITY_ANDROID
    quatMap = new Quaternion(gyro.attitude.w, gyro.attitude.x, gyro.attitude.y, gyro.attitude.z);
    #endif
    Quaternion q = quatMap * quatMult;
    Quaternion end = new Quaternion(q.w, q.x, q.y, q.z);
    transform.localRotation = end;

    #if (UNITY_IPHONE || UNITY_ANDROID)
    if (touchRotatesHeading)
    {
    GetTouchMouseInput();
    }
    camGrandparent.transform.localEulerAngles = new Vector3 (camGrandparent.transform.localEulerAngles.x,heading, camGrandparent.transform.localEulerAngles.z);
    #endif
    }

    void GetTouchMouseInput()
    {
    if (Input.GetMouseButtonDown(0))
    {
    mouseStartPoint = Input.mousePosition;
    headingAtTouchStart = heading;
    }
    else if (Input.GetMouseButton(0))
    {
    Vector2 delta;
    Vector2 mousePos = Input.mousePosition;
    delta.x = (mousePos.x - mouseStartPoint.x) / screenSize.x;
    delta.y = (mousePos.y - mouseStartPoint.y) / screenSize.y;
    heading = (headingAtTouchStart + delta.x * 100);
    heading = heading % 360;
    }
    }


    //void OnGUI()
    //{
    // // GUILayout.Label(origin.eulerAngles + " <- origin");
    // GUILayout.Label(Input.gyro.attitude.eulerAngles + " <- gyro");
    // GUILayout.Label(Quaternion.Inverse(Input.gyro.attitude).eulerAngles + " <- inv gyro");
    // GUILayout.Label(transform.localRotation.eulerAngles + " <- localRotation");
    //}

    }