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. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    Now that Unity 3.4 has support for the iPhone 4 gyroscope it makes a fantastic virtual camera controller.

    Took a bit of work to sort out the various orientation issues, so I thought I'd save anyone else the trouble.

    Example package attached. Enjoy!

    [updated so that it works even if camera already has a parent ie character controller etc]
     

    Attached Files:

    Last edited: Aug 8, 2011
  2. maglat

    maglat

    Joined:
    Jul 9, 2010
    Posts:
    111
    WOHOOO. Great work. Many thanks for sharing your work with us!
     
  3. I am da bawss

    I am da bawss

    Joined:
    Jun 2, 2011
    Posts:
    2,574
    Nice work! thanks for sharing!
     
  4. JanHelleman

    JanHelleman

    Joined:
    Oct 11, 2009
    Posts:
    116
    I was wondering if the user acceleration can be used to determine movement of the device itself in 3d space, rather then simply "moving" the camera...
     
  5. iLyxa

    iLyxa

    Joined:
    May 5, 2011
    Posts:
    2
    Great gyro attitude sample! tnx

    userAcceleration works in mistery mode... always Y+ and shaking. and after movement for example forward, returns back..
    i dont understend how it works! ((
     
  6. JanHelleman

    JanHelleman

    Joined:
    Oct 11, 2009
    Posts:
    116
    As far as I could determine so far the userAcceleration is a pure acceleration vector3. For some reason when you "stop" it moves "backwards", the acceleration get's less to a point where it goes to 0.
     
  7. bhaal

    bhaal

    Joined:
    Apr 18, 2009
    Posts:
    35
    Hi

    Great script!!
    I have a question: is there a way to start the camera facing always compass north?

    Cheers,
    Lucas
     
  8. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    @JanHelleman: I've played with the accelerometer, and it seems to be useless for translation; I think it's mostly good for getting tilt and shake. Wish it were otherwise.

    @bhaal: When you fire up the gyroscope, it starts out facing whatever direction the phone is facing. You'd need to read the compass to figure out which way is north (I think Prime31 has a plugin) and then you'd need to use a parent transform to compensate for whatever direction the phone is facing on startup.

    Glad it's been useful - I updated the package a little so that it uses only one script (now takes care of creating the necessary parent transform)
     
  9. Milad

    Milad

    Joined:
    Aug 17, 2010
    Posts:
    67
    Hi,
    I have tested your package but it does not work on my iPhone?!!!
     
  10. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    sure its an iphone4?
    other iphones dont have gyros
     
  11. squishydonut

    squishydonut

    Joined:
    Nov 6, 2010
    Posts:
    19
    Tilt on the X axis or all around? I was looking at some raw #s and it seems decent for the X-axis (i.e. car steering wheel).
     
  12. kiu

    kiu

    Joined:
    Jan 14, 2011
    Posts:
    10
    Thanks a lot. It's so wonderful when you want to do something and it's just been done for you! :)
     
  13. JanHelleman

    JanHelleman

    Joined:
    Oct 11, 2009
    Posts:
    116
    I was looking for very short distance movement of the device itself. After searching a lot I realized this gyro is A not precise enough for it and B there's to much error in the calculations according to some guy from google... To bad :)
     
  14. ikeo

    ikeo

    Joined:
    Jul 28, 2007
    Posts:
    51
    phoberman. This script is the bomb. Thanks for figuring this out man.
     
  15. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    phoberman that is a very handy script! I like it :).
    This script should be in the official unity wiki scripts section!!!!

    Has anyone tried to use that script with a Caracter Controller?
     
  16. Sortasoft

    Sortasoft

    Joined:
    Feb 24, 2009
    Posts:
    61
    This is a great script, thanks for sharing!

    One thing I've noticed is that when I rotate the phone around the Y axis (i.e. spinning the phone flat on a table), the image does not rotate as fast as the phone. For instance, when I rotate the phone 360 degrees, the image has only rotated about 270 degrees. The other axes seem to work great. Has anyone else noticed this? Any idea what's up?
     
  17. Sortasoft

    Sortasoft

    Joined:
    Feb 24, 2009
    Posts:
    61
    One additional detail that I've determined is that when I rotate the phone 90 in reality, it only registers as 70 degrees.
     
  18. iguana_02

    iguana_02

    Joined:
    Apr 22, 2011
    Posts:
    211
    Thank you for this! Its great!
     
  19. sandolkakos

    sandolkakos

    Joined:
    Jun 3, 2009
    Posts:
    282
    Thanks for sharing phoberman.
    Your gyroscope is working perfectly.
     
  20. redfox

    redfox

    Joined:
    Feb 24, 2011
    Posts:
    13
    Thank you so much for sharing! Great work!!!
     
  21. RHD

    RHD

    Joined:
    Mar 30, 2009
    Posts:
    719
    This is wonderful! Thank you!
    I have to figure out how to add it to a character controller next!

    I think I'm getting something wrong somewhere though, I'm getting flickering weirdness in the background. It's like it's repeating the screen image in layers over each other. Something to do with the refresh/frame rate?
    Any ideas what's causing this?

    Thanks.
     

    Attached Files:

    Last edited: Nov 27, 2011
  22. Running Pixel

    Running Pixel

    Joined:
    Mar 29, 2011
    Posts:
    31
    I would like to use this code for an AR app, but in this case would be useful to reset the Quaternion (or the eulers) to the magnetic compass heading (I know it is not accurate but better than have the cam oriented to East when it should be North...)
    Any idea how to do this?
     
  23. Thomas-Lund

    Thomas-Lund

    Joined:
    Jan 18, 2008
    Posts:
    465
    Hmmm - just tried building for iPad2 and iPhone 4S and the image is just static on the "Front Z+" part. Camera doesnt rotate at all.

    The Update() is called, bool is true and I can see the gyro.attitude values changing. Just doesnt change the camera.

    Any ideas?

    /Thomas
     
  24. sama-van

    sama-van

    Joined:
    Jun 2, 2009
    Posts:
    1,734
    Worked on a very similar feature at the beginning of this year :

    http://itunes.apple.com/us/app/id428087225?mt=8

    Maybe this could give you some ideas...
    I heard they was supposed to release the SDK, but I really dunno if they did.... o_O...
     
  25. yannminh

    yannminh

    Joined:
    Jul 1, 2007
    Posts:
    43
    wow... great... giant... thanks very much phoberman for your script...
     
  26. Deeeev

    Deeeev

    Joined:
    Oct 20, 2011
    Posts:
    1
    Cheers for the script!

    Just tried this on android now 3.5 supports it and works great.

    just needed to change
    gyroBool = Input.isGyroAvailable;
    with
    gyroBool = SystemInfo.supportsGyroscope;
     
  27. Funder75

    Funder75

    Joined:
    Jan 24, 2012
    Posts:
    7
    Hi

    The code works great, but it lacks support for ScreenOrientation.LandscapeRight and ScreenOrientation.PortraitUpsideDown.

    I can't get my head around how this works and would really appreciate if someone could tell me how to implement support for the missing screen orientations?? What should be in the ?? fileds below for the Vector3 and the Quaternion?

    Any help will be much appreciated.

    Regards
    Dan


    Code (csharp):
    1.        
    2. if (Screen.orientation == ScreenOrientation.LandscapeLeft)
    3. {
    4.     camParent.transform.eulerAngles = new Vector3(90,90,0);
    5.     rotFix = new Quaternion(0f,0f,0.7071f,0.7071f);
    6. }
    7. else if (Screen.orientation == ScreenOrientation.LandscapeRight)
    8. {
    9.     camParent.transform.eulerAngles = new Vector3(??,??,??);
    10.     rotFix = new Quaternion(??,??,??,??);
    11. }
    12. else if (Screen.orientation == ScreenOrientation.Portrait)
    13. {
    14.     camParent.transform.eulerAngles = new Vector3(90,180,0);
    15.     rotFix = new Quaternion(0f,0f,1f,0f);
    16. }
    17. if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)
    18. {
    19.     camParent.transform.eulerAngles = new Vector3(??,??,??);
    20.     rotFix = new Quaternion(??,??,??,??);
    21. }
    22.  
     
  28. BMStory

    BMStory

    Joined:
    Sep 28, 2011
    Posts:
    13
    I'm in the same boat as Funder75. Any way to add support for LanscapeRight?
     
  29. Funder75

    Funder75

    Joined:
    Jan 24, 2012
    Posts:
    7
    Yes, I actually did find the solution for LandscapeRight. Unfortunatly I'm stuck on the PortraitUpsideDown!


    Code (csharp):
    1. else if (Screen.orientation == ScreenOrientation.LandscapeRight)
    2.  
    3. {
    4.  
    5.     camParent.transform.eulerAngles = new Vector3(90,90,0);
    6.  
    7.     rotFix = new Quaternion(0f, 0f, -0.7071f, 0.7071f);
    8.  
    9. }
     
  30. Funder75

    Funder75

    Joined:
    Jan 24, 2012
    Posts:
    7
    With a lot of trial'n'error, some luck and a brief moment of clarity, I've succeeded in making all orientations work.
    I guess the code needs some cleaning up, but here it is...


    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GyroCam : MonoBehaviour
    5. {
    6.    
    7.     public CamManager target;
    8.     private bool gyroBool;
    9.     private Gyroscope gyro;
    10.     private Quaternion rotFix; 
    11.    
    12.     private GameObject camParent;
    13.     public ScreenOrientation currentOrientation;
    14.    
    15.     private bool initialized = false;
    16.     private Vector3 inititialRotation = new Vector3(90,90,0);
    17.    
    18.  
    19.    
    20.     private void init()
    21.     {
    22.         if (!initialized)
    23.         {
    24.             Transform originalParent = transform.parent; // check if this transform has a parent
    25.             camParent = new GameObject ("camParent"); // make a new parent
    26.             camParent.transform.position = transform.position; // move the new parent to this transform position
    27.             transform.parent = camParent.transform; // make this transform a child of the new parent
    28.             camParent.transform.parent = originalParent; // make the new parent a child of the original parent
    29.            
    30.             gyroBool = SystemInfo.supportsGyroscope;
    31.            
    32.             if (gyroBool) {
    33.                
    34.                 gyro = Input.gyro;
    35.                 gyro.enabled = true;
    36.                
    37.             }
    38.             else
    39.             {
    40.                 print("NO GYRO");
    41.             }
    42.            
    43.             initialized = true;
    44.         }
    45.     }
    46.    
    47.     private void updateScreenOrientation()
    48.     {
    49.         if (Screen.orientation == ScreenOrientation.LandscapeLeft)
    50.         {
    51.             camParent.transform.eulerAngles = inititialRotation;
    52.             rotFix = new Quaternion(0f,0f,0.7071f,0.7071f);
    53.         }
    54.         else if (Screen.orientation == ScreenOrientation.LandscapeRight)
    55.         {
    56.             camParent.transform.eulerAngles = inititialRotation;
    57.             rotFix = new Quaternion(0f,0f,-0.7071f,0.7071f);
    58.         }
    59.         else if (Screen.orientation == ScreenOrientation.Portrait)
    60.         {
    61.             camParent.transform.eulerAngles = inititialRotation;
    62.             rotFix = new Quaternion(0f,0f,1f,0f);
    63.         }
    64.         if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)
    65.         {
    66.             camParent.transform.eulerAngles = inititialRotation;
    67.             rotFix = new Quaternion(0f,0f,0f,1f);
    68.         }
    69.        
    70.                
    71.     }
    72.    
    73.     void Update ()
    74.     {
    75.         init();
    76.         if (currentOrientation != Screen.orientation)
    77.         {
    78.             currentOrientation = Screen.orientation;
    79.             updateScreenOrientation();
    80.         }      
    81.        
    82.         if (gyroBool)
    83.         {
    84.             Quaternion camRot = gyro.attitude * rotFix;
    85.             transform.localRotation = camRot;
    86.             target.SetRotation(transform.rotation);
    87.         }
    88.         else
    89.         {
    90.             target.SetRotation(Quaternion.identity);
    91.         }
    92.  
    93.     }
    94. }
     
  31. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    hi all -

    Thanks for all the kind words. I forgot to check this thread for a while but I'm glad the script has proven to be so popular and useful.

    In the meantime I've been working with Android as well as iOS, and I had to do a little work to get the code working on both.

    Here's my current script, works on both my phones (iPhone4 and Galaxy Nexus) - still haven't tackled anything except LandscapeLeft but now maybe I'll get around to it -


    Code (csharp):
    1. private var gyroBool : boolean;
    2. private var gyro : Gyroscope;
    3. private var quatMult : Quaternion;
    4. private var quatMap : Quaternion;
    5.  
    6. function Start() {
    7.     // find the current parent of the camera's transform
    8.     var currentParent = transform.parent;
    9.     // instantiate a new transform
    10.     var camParent = new GameObject ("camParent");
    11.     // match the transform to the camera position
    12.     camParent.transform.position = transform.position;
    13.     // make the new transform the parent of the camera transform
    14.     transform.parent = camParent.transform;
    15.     // make the original parent the grandparent of the camera transform
    16.     camParent.transform.parent = currentParent;
    17.     // check whether device supports gyroscope
    18.     #if UNITY_3_4
    19.     gyroBool = Input.isGyroAvailable;
    20.     #endif
    21.     #if UNITY_3_5
    22.     gyroBool = SystemInfo.supportsGyroscope;
    23.     #endif
    24.    
    25.     if (gyroBool) {
    26.         gyro = Input.gyro;
    27.         gyro.enabled = true;
    28.         #if UNITY_IPHONE
    29.             camParent.transform.eulerAngles = Vector3(90,90,0);
    30.             quatMult = Quaternion(0,0,0.7071,0.7071);
    31.         #endif
    32.         #if UNITY_ANDROID
    33.             camParent.transform.eulerAngles = Vector3(-90,0,0);
    34.             quatMult = Quaternion(0, 0, 0.7071, -0.7071);
    35.         #endif
    36.         Screen.sleepTimeout = 0;
    37.     } else {
    38.         #if UNITY_EDITOR
    39.             print("NO GYRO");
    40.         #endif
    41.     }
    42. }
    43.  
    44. function Update () {
    45.     if (gyroBool) {
    46.         #if UNITY_IPHONE
    47.             quatMap = gyro.attitude;
    48.         #endif
    49.         #if UNITY_ANDROID
    50.             quatMap = Quaternion(gyro.attitude.w,gyro.attitude.x,gyro.attitude.y,gyro.attitude.z);
    51.         #endif
    52.         transform.localRotation = quatMap * quatMult;
    53.     }
    54. }
    55.  
     
  32. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    Here's an update that covers all orientations - for both iOS Android

    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.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    57.                 quatMult = Quaternion(0f,0,0.7071,0.7071);
    58.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    59.                 quatMult = Quaternion(0,0,-0.7071,0.7071);
    60.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    61.                 quatMult = Quaternion(0,0,1,0);
    62.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    63.                 quatMult = new Quaternion(0,0,0,1);
    64.             }
    65.         #endif
    66.         #if UNITY_ANDROID
    67.             camParent.transform.eulerAngles = Vector3(-90,0,0);
    68.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    69.                 quatMult = Quaternion(0f,0,0.7071,-0.7071);
    70.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    71.                 quatMult = Quaternion(0,0,-0.7071,-0.7071);
    72.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    73.                 quatMult = Quaternion(0,0,0,1);
    74.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    75.                 quatMult = new Quaternion(0,0,1,0);
    76.             }
    77.         #endif
    78.         Screen.sleepTimeout = SleepTimeout.NeverSleep;
    79.     } else {
    80.         #if UNITY_EDITOR
    81.             //print("NO GYRO");
    82.         #endif
    83.     }
    84. }
    85.  
    86. function Update () {
    87.     if (gyroBool) {
    88.         #if UNITY_IPHONE
    89.             quatMap = gyro.attitude;
    90.         #endif
    91.         #if UNITY_ANDROID
    92.             quatMap = Quaternion(gyro.attitude.w,gyro.attitude.x,gyro.attitude.y,gyro.attitude.z);
    93.         #endif
    94.         transform.localRotation = quatMap * quatMult;
    95.     }
    96. }
    97.  
     
  33. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    Man Thanks Perry for the share !!!! and updated Code....
    i did update it myself and thought to post it here but you are faster and your Code look's more polished :)
    anyway many thanks for sharing.... in this times it is not often that this happen
    i really miss the good old time here in the forum where help sharing was normal...
     
  34. BlackSpider

    BlackSpider

    Joined:
    Oct 8, 2011
    Posts:
    43
    Wow really nice share.

    Does this also work on the Galaxy Tab? Because i don't have the right input..
    My screen is always rotated 90 degrees. Is this because it is build for phone?
     
  35. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    Here's another update - I added basic touch input so that a horizontal swipe rotates the heading.

    Black Spider, I would just experiment with the setting for camParent.transform.eulerAngles - try different rotations in 90 degree increments.

    By the way, this script is part of my very first package for the Asset Store - which just got approved!
    It's called FOV2GO and it's a comprehensive stereo 3D toolkit.
    Did I mention that it's FREE?
    Check it out: http://u3d.as/content/stereoskopix/fov2go

    pH


    Code (csharp):
    1. #pragma strict
    2. // Gyroscope-controlled camera for iPhone  Android revised 2.26.12
    3. // Stereoskopix FOV2GO Copyright (c) 2011 Perry Hoberman
    4. // Perry Hoberman <hoberman@bway.net>
    5. //
    6. // Usage:
    7. // Attach this script to main camera.
    8. // Note: Unity Remote does not currently support gyroscope.
    9. // Use Landscape Left for correct orientation
    10. //
    11. // This script uses three techniques to get the correct orientation out of the gyroscope attitude:
    12. // 1. creates a parent transform (camParent) and rotates it with eulerAngles
    13. // 2. for Android (Samsung Galaxy Nexus) only: remaps gyro.Attitude quaternion values from xyzw to wxyz (quatMap)
    14. // 3. multiplies attitude quaternion by quaternion quatMult
    15.  
    16. // Also creates a grandparent (camGrandparent) which can be rotated to change heading
    17. // This node allows an arbitrary heading to be added to the gyroscope reading
    18. // so that the virtual camera can be facing any direction in the scene, no matter which way the phone is actually facing
    19. // Option for touch input - horizontal swipe controls heading
    20.  
    21. static var gyroBool : boolean;
    22. private var gyro : Gyroscope;
    23. private var quatMult : Quaternion;
    24. private var quatMap : Quaternion;
    25. // camera grandparent node to rotate heading
    26. private var camGrandparent : GameObject;
    27. private var heading : float = 0;
    28.  
    29. // mouse/touch input
    30. public var touchRotatesHeading : boolean = true;
    31. private var screenSize : Vector2;
    32. private var mouseStartPoint: Vector2;
    33. private var headingAtTouchStart : float = 0;
    34. @script AddComponentMenu ("stereoskopix/s3d Gyro Cam")
    35.  
    36. function Awake() {
    37.     // find the current parent of the camera's transform
    38.     var currentParent = transform.parent;
    39.     // instantiate a new transform
    40.     var camParent = new GameObject ("camParent");
    41.     // match the transform to the camera position
    42.     camParent.transform.position = transform.position;
    43.     // make the new transform the parent of the camera transform
    44.     transform.parent = camParent.transform;
    45.     // instantiate a new transform
    46.     camGrandparent = new GameObject ("camGrandParent");
    47.     // match the transform to the camera position
    48.     camGrandparent.transform.position = transform.position;
    49.     // make the new transform the grandparent of the camera transform
    50.     camParent.transform.parent = camGrandparent.transform;
    51.     // make the original parent the great grandparent of the camera transform
    52.     camGrandparent.transform.parent = currentParent;
    53.        
    54.     // check whether device supports gyroscope
    55.     #if UNITY_3_4
    56.     gyroBool = Input.isGyroAvailable;
    57.     #endif
    58.     #if UNITY_3_5
    59.     gyroBool = SystemInfo.supportsGyroscope;
    60.     #endif
    61.    
    62.     if (gyroBool) {
    63.         gyro = Input.gyro;
    64.         gyro.enabled = true;
    65.         #if UNITY_IPHONE
    66.             camParent.transform.eulerAngles = Vector3(90,90,0);
    67.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    68.                 quatMult = Quaternion(0,0,0.7071,0.7071);
    69.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    70.                 quatMult = Quaternion(0,0,-0.7071,0.7071);
    71.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    72.                 quatMult = Quaternion(0,0,1,0);
    73.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    74.                 quatMult = Quaternion(0,0,0,1);
    75.             }
    76.         #endif
    77.         #if UNITY_ANDROID
    78.             camParent.transform.eulerAngles = Vector3(-90,0,0);
    79.             if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    80.                 quatMult = Quaternion(0,0,0.7071,-0.7071);
    81.             } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    82.                 quatMult = Quaternion(0,0,-0.7071,-0.7071);
    83.             } else if (Screen.orientation == ScreenOrientation.Portrait) {
    84.                 quatMult = Quaternion(0,0,0,1);
    85.             } else if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    86.                 quatMult = Quaternion(0,0,1,0);
    87.             }
    88.         #endif
    89.         Screen.sleepTimeout = SleepTimeout.NeverSleep;
    90.     } else {
    91.         #if UNITY_EDITOR
    92.             //print("NO GYRO");
    93.         #endif
    94.     }
    95. }
    96.  
    97. function Start() {
    98.     screenSize.x = Screen.width;
    99.     screenSize.y = Screen.height;
    100. }
    101.  
    102. function Update () {
    103.     if (gyroBool) {
    104.         #if UNITY_IPHONE
    105.             quatMap = gyro.attitude;
    106.         #endif
    107.         #if UNITY_ANDROID
    108.             quatMap = Quaternion(gyro.attitude.w,gyro.attitude.x,gyro.attitude.y,gyro.attitude.z);
    109.         #endif
    110.         transform.localRotation = quatMap * quatMult;
    111.     }
    112.     #if (UNITY_IPHONE || UNITY_ANDROID)  !UNITY_EDITOR
    113.         if (touchRotatesHeading) {
    114.             GetTouchMouseInput();
    115.         }
    116.         camGrandparent.transform.localEulerAngles.y = heading;
    117.     #endif
    118. }
    119.  
    120. function GetTouchMouseInput() {
    121.     if(Input.GetMouseButtonDown(0)) {
    122.         mouseStartPoint = Input.mousePosition;
    123.         headingAtTouchStart = heading;
    124.     } else if (Input.GetMouseButton(0)) {
    125.         var delta : Vector2;
    126.         var mousePos = Input.mousePosition;
    127.         delta.x = (mousePos.x - mouseStartPoint.x)/screenSize.x;
    128.         delta.y = (mousePos.y - mouseStartPoint.y)/screenSize.y;
    129.         heading = (headingAtTouchStart+delta.x*100);
    130.         heading = heading%360;
    131.     }
    132. }
    133.  
     
    Topillogical likes this.
  36. Mish

    Mish

    Joined:
    Apr 23, 2010
    Posts:
    96
    Great script! But how did you calculate which values to use for the rotation fix and why is it only necessary to calibrate in the Awake method and not Update?

    I noticed that it would always add 90 degrees to the Z rotation of the child camera, so I tried doing only this and still getting the same results as before:

    Code (csharp):
    1.  
    2. transform.parent.transform.eulerAngles = new Vector3 (90, 90, 0);
    3. Quaternion currentGyro = Input.gyro.attitude;
    4. transform.localRotation = currentGyro * Quaternion.Euler(0, 0, 90);
    5.  
     
    Last edited: Mar 21, 2012
  37. cbaltzer

    cbaltzer

    Joined:
    Jan 11, 2012
    Posts:
    120
    Thanks for the great script! Works like a charm on iOS, but I'm having some trouble on Android. Objects seem to drift with the camera, especially when moving side to side. I'm running in landscape left. Seems to be much better on the Galaxy Nexus, but other devices (Nexus S, Galaxy SII, etc) have terrible drift. Any ideas what might be causing this?

    Is Unity maybe faking the gyro input with accelerometer inputs?
     
  38. phoberman

    phoberman

    Joined:
    Jan 16, 2008
    Posts:
    74
    I would guess that the drift has more to do with the phone itself - drivers, OS, or gyroscope hardware - than with Unity.

    I was getting terrible results (probably similar to yours) on the LG Thrill 4G running Android 2.3 - just upgraded to Gingerbread - now the gyro works perfectly.
     
  39. nm8shun

    nm8shun

    Joined:
    Jul 14, 2007
    Posts:
    476
    First, phoberman, thanks so much for sharing...really a fun tool.

    I have a quick question though. Is there anyway to reset the camera back to a pre-defined location and then lock its location?

    I'm exploring something that I work with a couple of different cameras. And when I flip on a gyro camera (with your script), the location of the camera is always weird (as though the iPad's gyroscope has been keeping track of the camera all along and then passing that along to the gyro camera when its activated). I really want to be able to have that gyro camera stay in one place, but be able to look around from that fixed point....

    So thankful for any guidance or suggestions you could provide.
     
  40. yetstay

    yetstay

    Joined:
    Mar 28, 2012
    Posts:
    5
    nm8shun/ I am trying (relatively) the same thing myself and started a thread here, and here but no one seems to be interested so I will ask phoberman the same thing here...:)
     
  41. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Just curious - does this work on Unity 3.5? I got a version of this script to work in 3.4, but somehow iOS Update() gyro.attitude isn't refreshing (gyro.enabled evaluates as true)
     
  42. recognize

    recognize

    Joined:
    Mar 26, 2012
    Posts:
    3
    great! this is exactly what I was looking for. Always thought that accelerometer+compass was the way to go, but Gyro works perfectly! the quaternions for the different orientations are something I would not have found though... Great!

    Thanks.
     
  43. android_dev

    android_dev

    Joined:
    Jul 9, 2011
    Posts:
    19
    any updates to this script for using it with unity3.5 or to make it work with less jitter? Gyrodroid is working fine but it only works on android
     
  44. snovak

    snovak

    Joined:
    Sep 20, 2008
    Posts:
    1
    I will kiss you.. All of you.. You make me happy.
     
  45. yannminh

    yannminh

    Joined:
    Jul 1, 2007
    Posts:
    43
    Giant... thanks for sharing your AR Script... :)
     
  46. Drexster

    Drexster

    Joined:
    Feb 3, 2009
    Posts:
    20
    Awesome wicked script. Definitely useful! Thank you.

    I'm looking to limit the rotations between a min/max for the horizontal and vertical axes. What would be the best way to do this?
    I've tried using Mathf.Clamp on eulerAngles and applying these to transform.localEulerAngles with no joy.
    I'm terrible with Quaternions... quite frankly i don't understand them... so any help would be greatly appreciated!
     
  47. sinakarimi

    sinakarimi

    Joined:
    Jul 3, 2012
    Posts:
    1
    Hey it seems that the script link is broken? Am I doing something wrong?
     
  48. rsouza

    rsouza

    Joined:
    Dec 1, 2011
    Posts:
    67
    Im im some issues in Android Galaxy.

    All movement is ok, only a issue, when i move the camera to left to gyro go to other side.

    I think its wrong. Any answer?
     
  49. quitebuttery

    quitebuttery

    Joined:
    Mar 12, 2011
    Posts:
    327
    Yeah I'm seeing the same thing--on Android pitch is yaw and yaw is pitch.
     
  50. quitebuttery

    quitebuttery

    Joined:
    Mar 12, 2011
    Posts:
    327
    SOLVED IT!

    Turns out--android tablets are "natural" landscape and phones are "natural" portrait. So depending on what the natural orientation is, you have to flip the coordinates differently.

    Use this: https://gist.github.com/3252857

    To detect wether you are natural portrait or landscape.

    if you are landscape you have to flip the gyro coordinates like this:

    Code (csharp):
    1.  
    2. static Quaternion AndroidAltQuatMult()
    3.     {
    4.         Quaternion quatMult = Quaternion.identity;
    5.        
    6.         if (Screen.orientation == ScreenOrientation.PortraitUpsideDown) {
    7.              quatMult = new Quaternion(0f,0f,0.7071f,-0.7071f);
    8.         } else if (Screen.orientation == ScreenOrientation.Portrait) {
    9.              quatMult = new Quaternion(0f,0f,-0.7071f,-0.7071f);
    10.         } else if (Screen.orientation == ScreenOrientation.LandscapeRight) {
    11.             quatMult = new Quaternion(0f,0f,0f,1f);
    12.        } else if (Screen.orientation == ScreenOrientation.LandscapeLeft) {
    13.             quatMult = new Quaternion(0f,0f,1f,0f);
    14.       }
    15.        
    16.         return(quatMult);
    17.     }
    18.  
     
    canis likes this.