unity 陀螺仪 物体旋转和移动效果

unity 陀螺仪 物体旋转和移动效果
直接上码 带注释

public class SDKGyroController : MonoBehaviour {
//陀螺仪是否存在

    class GyroGameObject
    {
       public GameObject go = null;
       public bool m_IsRotate = false;
       public bool m_IsBack = false;
       public Vector3 m_StartVec3 = Vector3.zero;
       public float m_RangeX = 0;
       public float m_RangeY = 0;
       public float m_SpeedX = 0;
       public float m_SpeedY = 0;
       public float m_LerpParam = 0;
       public float lastDiff_X;
       public float lastDiff_Y;
       public void Clear()
       {
           go = null;
       }
       public void ReSet()
       {
           if (go != null)
           {
               go.transform.localPosition = m_StartVec3;
           }
       }
    }
    private List<GyroGameObject> gyroGameObjects = new List<GyroGameObject>();

    private bool gyroBool;
    public bool isGyro = true;
    //陀螺仪
    private Gyroscope gyro = null;

    private float m_StartGyroX;
    private float m_StartGyroY;

    //陀螺仪x轴的取值
    private float m_CurGyroX = 0f;
    private float m_CurGyroY = 0f;

    private float diff_X = 0f;
    private float diff_Y = 0f;

    private float valueGyroX = 0f;
    private float valueGyroY = 0f;
    // 调用,用来添加一个控制器脚本
    public static void AddGyroComponent(GameObject gameObject, float rangeX, float rangeY, float speedX, float speedY, float lerpValue)
    {
        SDKGyroController gm = gameObject.GetComponent<SDKGyroController>();
        if (gm == null)
            gm = gameObject.AddComponent<SDKGyroController>();
        gm.AddGyroGameObject(gameObject, rangeX, rangeY, speedX, speedY, lerpValue);
    }
    //调用,用来添加一个GameObject做移动旋转效果
    //默认为移动 isRotate true 为旋转
    //isBack 旋转方向和陀螺仪方向是否相反
    public void AddGyroGameObject(GameObject gameObject, float rangeX, float rangeY, float speedX, float speedY, float lerpValue,bool isRotate = false,bool isBack = false)
    {
        GyroGameObject gyro = new GyroGameObject();
        gyro.go = gameObject;
        gyro.m_IsRotate = isRotate;
        gyro.m_IsBack = isBack;
        if (isRotate)
            gyro.m_StartVec3 = new Vector3(gameObject.transform.localEulerAngles.x, gameObject.transform.localEulerAngles.y, gameObject.transform.localEulerAngles.z);
        else
        {
            gyro.m_StartVec3 = new Vector3(gameObject.transform.localPosition.x, gameObject.transform.localPosition.y, gameObject.transform.localPosition.z);
        }
        gyro.m_RangeX = rangeX;
        gyro.m_RangeY = rangeY;
        gyro.m_SpeedX = speedX;
        gyro.m_SpeedY = speedY;
        gyro.m_LerpParam = lerpValue;
        gyroGameObjects.Add(gyro);
    }
    public void Clear()
    {
        for (int i = 0; i < gyroGameObjects.Count; i++)
        {
            if (gyroGameObjects[i] != null)
            {
                gyroGameObjects[i].Clear();
            }
        }
        gyroGameObjects.Clear();
    }
    public void Clear(GameObject go)
    {
        for (int i = 0; i < gyroGameObjects.Count; i++)
        {
            if (gyroGameObjects[i].go == go)
            {
                gyroGameObjects.Remove(gyroGameObjects[i]);
                break;
            }
        }
    }
    void OnDestroy()
    {
        Clear();
    }
    void Awake()
    {
#if !UNITY_EDITOR
        //判断是否支持陀螺仪
        gyroBool = SystemInfo.supportsGyroscope;
#else
        gyroBool = true;
#endif


#if !UNITY_EDITOR
        //给陀螺仪赋值
        gyro = Input.gyro;
        if (gyro != null)
        {
            gyroBool = true;
            gyro.enabled = true;
        }
#endif
    }

    private void Start()
    {
        if (gyroBool)
        {
#if !UNITY_EDITOR
            m_StartGyroX = gyro.gravity.x;
            m_StartGyroY = gyro.gravity.y;
#else
            valueGyroX = 0;
            valueGyroY = 0;
            m_StartGyroX = valueGyroX;
            m_StartGyroY = valueGyroY;
#endif
        }
    }
    public void ReSet()
    {
        for (int i = 0; i < gyroGameObjects.Count; i++)
        {
            if (gyroGameObjects[i] != null) gyroGameObjects[i].ReSet();
        }
    }
    int m_upate_rate = 30;
    void Update()
    {
        Input.gyro.updateInterval = 1.0f / m_upate_rate;
        //位置随着陀螺仪重力感应的X轴变化而变化
        if (gyroBool && isGyro)
        {
            for (int i = 0; i < gyroGameObjects.Count; i++)
            {
                if (gyroGameObjects[i].m_IsRotate)
                {
                    RotateGameObject(gyroGameObjects[i]);
                }
                else
                {
                    TransformGameObject(gyroGameObjects[i]);
                }
            }
        }
    }

    private float curPosX = 0f;
    private float curPosY = 0f;
    //移动操作
    void TransformGameObject(GyroGameObject gyroGameObject)
    {
        if (gyroGameObject == null || gyroGameObject.go == null)
            return;
#if UNITY_EDITOR
        m_CurGyroX = valueGyroX;
        m_CurGyroY = valueGyroY;
#else
        m_CurGyroX = gyro.gravity.x;
        m_CurGyroY = gyro.gravity.y;
#endif
        if (gyroGameObject.m_IsBack)
        {
            m_CurGyroX = 0 - m_CurGyroX;
            m_CurGyroY = 0 - m_CurGyroY;
        }
        diff_X = m_CurGyroX - m_StartGyroX;
        diff_Y = m_CurGyroY - m_StartGyroY;

        float xx = Mathf.Lerp(0, diff_X, gyroGameObject.m_LerpParam);
        float yy = Mathf.Lerp(0, diff_Y, gyroGameObject.m_LerpParam);

        Vector3 v3 = new Vector3(xx * gyroGameObject.m_SpeedX, yy * gyroGameObject.m_SpeedY, 0);

        Vector3 curVec3 = gyroGameObject.go.transform.localPosition;

        if (v3.x > gyroGameObject.m_RangeX)
        {
            curPosX = gyroGameObject.m_StartVec3.x + gyroGameObject.m_RangeX;
            if (gyroGameObject.lastDiff_X > diff_X)
            {
                m_StartGyroX = m_CurGyroX - gyroGameObject.m_RangeX / gyroGameObject.m_SpeedX;
            }
        }
        else if (v3.x < -gyroGameObject.m_RangeX)
        {
            curPosX = gyroGameObject.m_StartVec3.x - gyroGameObject.m_RangeX;
            if (gyroGameObject.lastDiff_X < diff_X)
            {
                m_StartGyroX = m_CurGyroX + gyroGameObject.m_RangeX / gyroGameObject.m_SpeedX;
            }
        }
        else
        {
            float fx = Mathf.Lerp(curVec3.x, gyroGameObject.m_StartVec3.x + v3.x, gyroGameObject.m_LerpParam);
            curPosX = fx;
        }

        if (v3.y > gyroGameObject.m_RangeY)
        {
            curPosY = gyroGameObject.m_StartVec3.y + gyroGameObject.m_RangeY;
            if (gyroGameObject.lastDiff_Y > diff_Y)
            {
                m_StartGyroY = m_CurGyroY - gyroGameObject.m_RangeY / gyroGameObject.m_SpeedY;
            }
        }
        else if (v3.y < -gyroGameObject.m_RangeY)
        {
            curPosY = gyroGameObject.m_StartVec3.y - gyroGameObject.m_RangeY;
            if (gyroGameObject.lastDiff_Y < diff_Y)
            {
                m_StartGyroY = m_CurGyroY + gyroGameObject.m_RangeY / gyroGameObject.m_SpeedY;
            }
        }
        else
        {
            float fy = Mathf.Lerp(curVec3.y, gyroGameObject.m_StartVec3.y + v3.y, gyroGameObject.m_LerpParam);
            curPosY = fy;
        }

        gyroGameObject.go.transform.localPosition = new Vector3(curPosX, curPosY, gyroGameObject.m_StartVec3.z);

        gyroGameObject.lastDiff_X = diff_X;
        gyroGameObject.lastDiff_Y = diff_Y;

        diff_X = 0;
        diff_Y = 0;
    }
    //旋转操作
    void RotateGameObject(GyroGameObject gyroGameObject)
    {
        if (gyroGameObject == null || gyroGameObject.go == null)
            return;
#if UNITY_EDITOR
        m_CurGyroX = valueGyroX;
#else
        m_CurGyroX = gyro.gravity.x;
#endif
        if (gyroGameObject.m_IsBack)
        {
            m_CurGyroX = 0 - m_CurGyroX;
        }
        float defY = gyroGameObject.m_StartVec3.y;
        float tagetY = m_CurGyroX * gyroGameObject.m_SpeedX + defY;
        if (tagetY < defY - gyroGameObject.m_RangeX)
        {
            tagetY = defY - gyroGameObject.m_RangeX;
        }
        else if (tagetY > defY + gyroGameObject.m_RangeX)
        {
            tagetY = defY + gyroGameObject.m_RangeX;
        }
        //插值计算平滑一点
        Quaternion taget = Quaternion.Euler(gyroGameObject.go.transform.localEulerAngles.x, tagetY, gyroGameObject.go.transform.localEulerAngles.z);
        gyroGameObject.go.transform.rotation = Quaternion.Slerp(gyroGameObject.go.transform.rotation, taget, Time.deltaTime * gyroGameObject.m_LerpParam);
    }
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Unity 中的陀螺仪 API 来获取设备的陀螺仪数据,然后将其映射到鼠标和键盘控制上。具体实现步骤如下: 1. 使用 `Input.gyro.enabled` 属性启用设备的陀螺仪。 2. 使用 `Input.gyro.attitude` 属性获取设备的欧拉角(yaw、pitch、roll)。 3. 对欧拉角进行处理,将其映射到鼠标移动和键盘控制上。例如,可以将 yaw 映射到水平方向的移动,pitch 映射到垂直方向的移动,roll 映射到旋转控制上。 4. 使用 Unity 中的 Input 类来模拟鼠标和键盘控制,实现鼠标的移动、点击和键盘的按键等功能。 以下是一个示例代码,实现了使用陀螺仪控制鼠标移动和方向的功能: ```csharp using UnityEngine; public class GyroControl : MonoBehaviour { public float sensitivity = 5.0f; // 控制灵敏度 public float speed = 5.0f; // 移动速度 public float rotationSpeed = 10.0f; // 旋转速度 private Vector3 lastEuler; private Vector3 currentEuler; void Start() { // 启用陀螺仪 Input.gyro.enabled = true; // 初始化欧拉角 lastEuler = Vector3.zero; currentEuler = Vector3.zero; } void Update() { // 获取陀螺仪数据 Quaternion gyroAttitude = Input.gyro.attitude; Vector3 gyroEuler = gyroAttitude.eulerAngles; currentEuler = new Vector3(-gyroEuler.y, gyroEuler.x, gyroEuler.z); // 计算欧拉角变化量 Vector3 deltaEuler = currentEuler - lastEuler; lastEuler = currentEuler; // 映射到鼠标移动和键盘控制 float mouseX = Input.GetAxis("Mouse X") + deltaEuler.x * sensitivity; float mouseY = Input.GetAxis("Mouse Y") + deltaEuler.y * sensitivity; float horizontal = deltaEuler.x * speed; float vertical = deltaEuler.y * speed; float rotation = deltaEuler.z * rotationSpeed; // 控制鼠标移动 Input.mousePosition = new Vector3(mouseX, mouseY, 0); // 控制键盘控制 Vector3 movement = new Vector3(horizontal, 0, vertical); transform.Translate(movement * Time.deltaTime); transform.Rotate(Vector3.up, rotation); } } ``` 需要注意的是,该代码仅作为示例,实际使用时需要根据具体情况进行调整。同时,还需要考虑用户体验,确保鼠标和键盘控制的灵敏度和平滑度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值