Search Unity

[Sharing] Gyroscope Camera Script (iOS tested)

Discussion in 'iOS and tvOS' started by franktinsley, Apr 21, 2014.

  1. franktinsley

    franktinsley

    Joined:
    Jul 1, 2010
    Posts:
    130
    Hey guys, I got a bit obsessed with understanding exactly how to adjust the quaternion in Input.gyro.attitude to work as a good camera rotation. I never did really grasp quaternions as I hoped but I have created a gyro camera script that I think may be helpful to others. Here it is!

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GyroCamera : MonoBehaviour
    5. {
    6.     private float initialYAngle = 0f;
    7.     private float appliedGyroYAngle = 0f;
    8.     private float calibrationYAngle = 0f;
    9.  
    10.     void Start()
    11.     {
    12.         Application.targetFrameRate = 60;
    13.         initialYAngle = transform.eulerAngles.y;
    14.     }
    15.  
    16.     void Update()
    17.     {
    18.         ApplyGyroRotation();
    19.         ApplyCalibration();
    20.     }
    21.  
    22.     void OnGUI()
    23.     {
    24.         if( GUILayout.Button( "Calibrate", GUILayout.Width( 300 ), GUILayout.Height( 100 ) ) )
    25.         {
    26.             CalibrateYAngle();
    27.         }
    28.     }
    29.  
    30.     public void CalibrateYAngle()
    31.     {
    32.         calibrationYAngle = appliedGyroYAngle - initialYAngle; // Offsets the y angle in case it wasn't 0 at edit time.
    33.     }
    34.    
    35.     void ApplyGyroRotation()
    36.     {
    37.         transform.rotation = Input.gyro.attitude;
    38.         transform.Rotate( 0f, 0f, 180f, Space.Self ); // Swap "handedness" of quaternion from gyro.
    39.         transform.Rotate( 90f, 180f, 0f, Space.World ); // Rotate to make sense as a camera pointing out the back of your device.
    40.         appliedGyroYAngle = transform.eulerAngles.y; // Save the angle around y axis for use in calibration.
    41.     }
    42.  
    43.     void ApplyCalibration()
    44.     {
    45.         transform.Rotate( 0f, -calibrationYAngle, 0f, Space.World ); // Rotates y angle back however much it deviated when calibrationYAngle was saved.
    46.     }
    47. }
    And (in case your browser also doesn't get clean code from this board) here it is in a file: https://dl.dropboxusercontent.com/u/10622911/GyroCamera.cs
     
  2. sorushe-mehre

    sorushe-mehre

    Joined:
    Aug 12, 2013
    Posts:
    8
    thank you for ios
    but does not work on android.
     
  3. Wom

    Wom

    Joined:
    Feb 7, 2013
    Posts:
    38
    Hi Frank,

    Big thanks. I really didn't want to be messing about with this - certainly helped me get started.

    Note: the gyro seems to be disabled by default on Android, all that's necessary for this to work is to add this as the first line of the Start() method:
    Code (csharp):
    1. Input.gyro.enabled = true;
    I'm not really doing much with it - just letting the user rotate the background camera and haven't tested different orientations or anything yet.
    Tested on a Nexus 5 and a Nexus 7, seems to be working fine.
     
    lamyikting and BjoUnity3d like this.
  4. radicalunity

    radicalunity

    Joined:
    Aug 5, 2014
    Posts:
    1
    Thanks! -- to make this work correctly on android I had to change the transforms to this:
    #ifUNITY_ANDROID
    transform.Rotate( 0f, 0f, 180f, Space.Self ); //Swap "handedness" ofquaternionfromgyro.
    transform.Rotate( 270f, 180f, 180f, Space.World ); //Rotatetomakesenseasacamerapointingoutthebackofyourdevice.
    #else
    transform.Rotate( 0f, 0f, 180f, Space.Self ); //Swap "handedness" ofquaternionfromgyro.
    transform.Rotate( 90f, 180f, 0f, Space.World ); //Rotatetomakesenseasacamerapointingoutthebackofyourdevice.
    #endif

    Otherwise, it was upside down and the gyro would move you in the opposite direction that you want to be viewing in.

    It's a cleaner solution than what I was doing before (and which didn't always work) -- making a cam parent and double-transforming
     
  5. _Adriaan

    _Adriaan

    Joined:
    Nov 12, 2009
    Posts:
    481
    Reviving ancient threads - my favourite thing in life.

    Does anyone have a suggestion how to also align the world to the magnetic north?
     
  6. xcesar

    xcesar

    Joined:
    Apr 30, 2013
    Posts:
    1
    Haw to set Limit of Rotation?
     
    GamerBoxStudios likes this.
  7. wbknox

    wbknox

    Joined:
    Aug 1, 2016
    Posts:
    11
  8. Hybridizer

    Hybridizer

    Joined:
    Feb 3, 2015
    Posts:
    18
    I love this script, helped me add a VR element to my driving game (after adding the "Input.gyro.enabled=true;" section, which was a much easier fix than expected), but I have a somewhat important question: How can the GameObject with this script attached be manipulated by a parent object? Using my setup as an example, I'd like to place the camera rig in the car, how can I make the camera move with the car, while still allowing me to alter the local angles with my gyro device? I'd like my camera to turn/ move with the car, but still be able to pivot from that relative angle, such as looking out the window. Any help would be greatly appreciated.

    Small side note: I'd also like to be able to move the Calibrate button to the top center of the screen, or control it with a separate Canvas button, but cannot find a clear explanation of how to do this in this specific setup.
     
  9. zero_null

    zero_null

    Joined:
    Mar 11, 2014
    Posts:
    159
    Hi Guys the script seems to be working perfectly with Unity 5.4.2 but I have a problem. The child of the camera don't follow parent correctly. What could be the reason?
     
  10. NicoFad

    NicoFad

    Joined:
    Dec 7, 2016
    Posts:
    2
    I have a similar problem, once the rotation stops, it keeps moving for a while until it stops again.
     
    Fangh and mike_gnap like this.
  11. artics

    artics

    Joined:
    Sep 17, 2013
    Posts:
    8
    thank you very much!
     
  12. gringofxs

    gringofxs

    Joined:
    Oct 14, 2012
    Posts:
    240
    Hi, did you find a solution to stop the object while stop rotate?
     
    mike_gnap likes this.
  13. 3162497047

    3162497047

    Joined:
    Mar 2, 2017
    Posts:
    2
    Anyway thank you ~
     
  14. Archviz3d

    Archviz3d

    Joined:
    Apr 4, 2016
    Posts:
    92
    Amazing job!! Thank you so much!! Simple script but saved me hours/days trying to figuring out how the hell this all work correctly!!! My previous intent wasnt working as good as this!!! Its working very good with android 7.0 on a samsung s7 and a build from unity 2017.1
     
  15. jamal-dahbur

    jamal-dahbur

    Joined:
    Jul 24, 2014
    Posts:
    8
    Awesome! Any luck making it smoother?? I mean decrease the sensitivity
     
  16. blamejane

    blamejane

    Joined:
    Jul 8, 2013
    Posts:
    233
    Glad you like reviving old threads cuz I need your help...

    Did you ever find out how to also align to magnetic north?
     
  17. GamerBoxStudios

    GamerBoxStudios

    Joined:
    Feb 4, 2016
    Posts:
    1
    Did you find out how to limit the rotation perfectly?! because I don't seem to have it working very well for me always there is glitching!
    thanks in advance
     
  18. GuardFromUA

    GuardFromUA

    Joined:
    Jan 11, 2017
    Posts:
    8
    Does anyone implemented swipe here? Trying to use swipe and gyro while viewing 360 videos like on Youtube, but have no success at this moment.
     
  19. Hybridizer

    Hybridizer

    Joined:
    Feb 3, 2015
    Posts:
    18
    You could add an extra Transform.Rotate to the Y and X axes (for horizontal and vertical movement respectively), and use Input.GetTouch to measure finger movement, as such:

    Code (CSharp):
    1. public float touchRotAdjust = 1f;
    2.  
    3. Update () {
    4.  
    5. if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
    6.         {
    7.             // Get movement of the finger since last frame
    8.             Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
    9.  
    10.             // Add this part after the other Rotation lines
    11.             transform.Rotate(touchDeltaPosition.y * touchRotAdjust, touchDeltaPosition.x * touchRotAdjust, 0f, Space.Self);
    12.         }
    13.  
    14. }
    The above is not tested and will likely require testing and fanoodling to get how you want, but that's how I'd approach it. You could also multiply touchDeltaPosition's values by another float, one that Lerps to zero after you stop touching to simulate inertia.

    Hope this helps!
     
  20. Marc0101

    Marc0101

    Joined:
    Apr 20, 2017
    Posts:
    7
    Hi guys! Great script!
    I have an issue with adding the touch/swipe. Someone can give more info about the code implementation? Thanks!
     
  21. Hybridizer

    Hybridizer

    Joined:
    Feb 3, 2015
    Posts:
    18
    Depends on what Input setup you're using. Are you using the classic Input Manager (Input.GetTouch, GetKeyDown, etc) or Unity's new Input System package? My above example should be a sufficient starting point (make sure to add "using UnityEngine.Input" at the top of your code). Otherwise, Unity's new system includes a Touch option for handling multiple touches and devices.

    Here's a good place to start with Unity's new Input System touch handling:
    https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Touch.html
     
  22. rgbsandman

    rgbsandman

    Joined:
    Feb 8, 2019
    Posts:
    2
    A
    as of unity 2109.4.20 i see gyro.attitude perfectly aligning to magnetic north in my htc (after the android corrections)