文档章节

Unity陀螺仪

 江湖令
发布于 2015/09/02 14:22
字数 554
阅读 945
收藏 0

       最近公司要在项目中添加一个类似IbutterFly中的收集精灵的功能,便开始研究陀螺仪。要使用陀螺仪必须开始陀螺仪,不然在手机上没有效果。开启的方式很简单:Input.gyro.enabled =true,但是也折腾了好几个小时。发现一个控制陀螺仪旋转的脚本很不错就和大家分享下。

// ***********************************************************
// Written by Heyworks Unity Studio http://unity.heyworks.com/
// ***********************************************************
using UnityEngine;

/// <summary>
/// Gyroscope controller that works with any device orientation.
/// </summary>
public class GyroController : MonoBehaviour 
{
    #region [Private fields]

    private bool gyroEnabled = true;
    private const float lowPassFilterFactor = 0.2f;

    private readonly Quaternion baseIdentity =  Quaternion.Euler(90, 0, 0);
    private readonly Quaternion landscapeRight =  Quaternion.Euler(0, 0, 90);
    private readonly Quaternion landscapeLeft =  Quaternion.Euler(0, 0, -90);
    private readonly Quaternion upsideDown =  Quaternion.Euler(0, 0, 180);
    
    private Quaternion cameraBase =  Quaternion.identity;
    private Quaternion calibration =  Quaternion.identity;
    private Quaternion baseOrientation =  Quaternion.Euler(90, 0, 0);
    private Quaternion baseOrientationRotationFix =  Quaternion.identity;

    private Quaternion referanceRotation = Quaternion.identity;
    private bool debug = true;

    #endregion

    #region [Unity events]

    protected void Start () 
    {
        AttachGyro();
    }

    protected void Update() 
    {
        if (!gyroEnabled)
            return;


        transform.rotation = Quaternion.Slerp(transform.rotation,
            cameraBase * ( ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), lowPassFilterFactor);
        //transform.eulerAngles = new Vector3 (transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y,0f);
    }

    protected void OnGUI()
    {
        if (!debug)
            return;

        GUILayout.Label("Orientation: " + Screen.orientation);
        GUILayout.Label("Calibration: " + calibration);
        GUILayout.Label("Camera base: " + cameraBase);
        GUILayout.Label("input.gyro.attitude: " + Input.gyro.attitude);
        GUILayout.Label("transform.rotation: " + transform.rotation);
        GUILayout.Label("transform.rotaion: "+ transform.eulerAngles);
        if (GUILayout.Button("On/off gyro: " + Input.gyro.enabled, GUILayout.Height(100)))
        {
            Input.gyro.enabled = !Input.gyro.enabled;
        }

        if (GUILayout.Button("On/off gyro controller: " + gyroEnabled, GUILayout.Height(100)))
        {
            if (gyroEnabled)
            {
                DetachGyro();
            }
            else
            {
                AttachGyro();
            }
        }

        if (GUILayout.Button("Update gyro calibration (Horizontal only)", GUILayout.Height(80)))
        {
            UpdateCalibration(true);
        }

        if (GUILayout.Button("Update camera base rotation (Horizontal only)", GUILayout.Height(80)))
        {
            UpdateCameraBaseRotation(true);
        }

        if (GUILayout.Button("Reset base orientation", GUILayout.Height(80)))
        {
            ResetBaseOrientation();
        }

        if (GUILayout.Button("Reset camera rotation", GUILayout.Height(80)))
        {
            transform.rotation = Quaternion.identity;
        }
    }

    #endregion

    #region [Public methods]

    /// <summary>
    /// Attaches gyro controller to the transform.
    /// </summary>
    private void AttachGyro()
    {
        gyroEnabled = true;
        ResetBaseOrientation();
        UpdateCalibration(true);
        UpdateCameraBaseRotation(true);
        RecalculateReferenceRotation();
    }

    /// <summary>
    /// Detaches gyro controller from the transform
    /// </summary>
    private void DetachGyro()
    {
        gyroEnabled = false;
    }

    #endregion

    #region [Private methods]

    /// <summary>
    /// Update the gyro calibration.
    /// </summary>
    private void UpdateCalibration(bool onlyHorizontal)
    {
        if (onlyHorizontal)
        {
            var fw = (Input.gyro.attitude) * (-Vector3.forward);
            fw.z = 0;
            if (fw == Vector3.zero)
            {
                calibration = Quaternion.identity;
            }
            else
            {
                calibration = (Quaternion.FromToRotation(baseOrientationRotationFix * Vector3.up, fw));
            }
        }
        else
        {
            calibration = Input.gyro.attitude;
        }
    }
    
    /// <summary>
    /// Update the camera base rotation.
    /// </summary>
    /// <param name='onlyHorizontal'>
    /// Only y rotation.
    /// </param>
    private void UpdateCameraBaseRotation(bool onlyHorizontal)
    {
        if (onlyHorizontal)
        {
            var fw = transform.forward;
            fw.y = 0;
            if (fw == Vector3.zero)
            {
                cameraBase = Quaternion.identity;
            }
            else
            {
                cameraBase = Quaternion.FromToRotation(Vector3.forward, fw);
            }
        }
        else
        {
            cameraBase = transform.rotation;
        }
    }
    
    /// <summary>
    /// Converts the rotation from right handed to left handed.
    /// </summary>
    /// <returns>
    /// The result rotation.
    /// </returns>
    /// <param name='q'>
    /// The rotation to convert.
    /// </param>
    private static Quaternion ConvertRotation(Quaternion q)
    {
        return new Quaternion(q.x, q.y, -q.z, -q.w);    
    //    return new Quaternion(-q.x, -q.y, 0f, 0f);    
    }
    
    /// <summary>
    /// Gets the rot fix for different orientations.
    /// </summary>
    /// <returns>
    /// The rot fix.
    /// </returns>
    private Quaternion GetRotFix()
    {
#if UNITY_3_5
        if (Screen.orientation == ScreenOrientation.Portrait)
            return Quaternion.identity;
        
        if (Screen.orientation == ScreenOrientation.LandscapeLeft || Screen.orientation == ScreenOrientation.Landscape)
            return landscapeLeft;
                
        if (Screen.orientation == ScreenOrientation.LandscapeRight)
            return landscapeRight;
                
        if (Screen.orientation == ScreenOrientation.PortraitUpsideDown)
            return upsideDown;
        return Quaternion.identity;
#else
        return Quaternion.identity;
#endif
    }
    
    /// <summary>
    /// Recalculates reference system.
    /// </summary>
    private void ResetBaseOrientation()
    {
        baseOrientationRotationFix = GetRotFix();
        baseOrientation = baseOrientationRotationFix * baseIdentity;
    }

    /// <summary>
    /// Recalculates reference rotation.
    /// </summary>
    private void RecalculateReferenceRotation()
    {
        referanceRotation = Quaternion.Inverse(baseOrientation)*Quaternion.Inverse(calibration);
    }

    #endregion
}




© 著作权归作者所有

共有 人打赏支持
粉丝 1
博文 74
码字总数 15154
作品 0
西安
私信 提问
Razer 发布 199 美金的开源虚拟现实头戴设备

Razer 是一个游戏电脑和外围设备的制造厂商,刚刚宣布进军虚拟现实空间,在 CES 上推出一款标价 199 美金的 OSVR Hacker Dev Kit 头戴设备。该设备将在今年 6 月份推出。 同时 Razer 还发布一...

oschina
2015/01/07
2.1K
18
VMware Workstation 10.0 正式发布

VMware Workstation是一款功能强大的虚拟机软件,可以使你在一台机器上同时运行二个或更多Windows、DOS、LINUX系统,并进行开发、测试、部署新的应用程序。 今天,VMware Workstation 10.0正...

oschina
2013/09/04
3.8K
41
kinect和unity3d问题

KinectWrapperPackage导入unity3d绑定的人模,为什么只能四肢动,不能跟人发生位移,距离体感仪近了或远了,人模就发生严重的变形呢?

baijiwu
2014/12/23
631
0
Unity3D平台依赖编译

Platform Defines The platform defines that Unity supports for your scripts are: Property: Function: UNITY_EDITOR Define for calling Unity Editor scripts from your game code. UNI......

xxx111ooo
2015/11/12
1
0
Mock的基本概念和方法(续)

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正! Content 0. 序 1. 平台 2. 第三方库 3. 如何使用CMock和Unity...

晨曦之光
2012/03/09
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

C++ vector和list的区别

1.vector数据结构 vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。 因此能高效的进行随机存取,时间复杂度为o(1); 但因为内存空间是连续的,所以在进行插入和删除操作时,会造...

shzwork
18分钟前
0
0
Spring之invokeBeanFactoryPostProcessors详解

Spring的refresh的invokeBeanFactoryPostProcessors,就是调用所有注册的、原始的BeanFactoryPostProcessor。 相关源码 public static void invokeBeanFactoryPostProcessors(Configu......

cregu
昨天
0
0
ibmcom/db2express-c_docker官方使用文档

(DEPRECIATED) Please check DB2 Developer-C Edition for the replacement. What is IBM DB2 Express-C ? ``IBM DB2 Express-C``` is the no-charge community edition of DB2 server, a si......

BG2KNT
昨天
0
0
Ubuntu 18.04.2 LTS nvidia-docker2 : 依赖: docker-ce (= 5:18.09.0~3-0~ubuntu-bionic)

平台:Ubuntu 18.04.2 LTS nvidia-docker2 版本:2.0.3 错误描述:在安装nvidia-docker2的时候报dpkg依赖错误 nvidia-docker2 : 依赖: docker-ce (= 5:18.09.0~3-0~ubuntu-bionic) 先看一下依......

Pulsar-V
昨天
3
0
学习笔记1-goland结构体(struct)

写在前面:若有侵权,请发邮件by.su@qq.com告知。 转载者告知:如果本文被转载,但凡涉及到侵权相关事宜,转载者需负责。请知悉! 本文永久更新地址:https://my.oschina.net/bysu/blog/3036...

不最醉不龟归
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部