【Unity】适用于AR相机的手势脚本,旋转平移缩放

5 篇文章 0 订阅
3 篇文章 0 订阅

专门针对AR相机的手势操作脚本,包含旋转平移缩放功能。
有小伙伴们觉得可以优化的地方请把行数及优化代码一起留言至评论区。
废话不多说,直接上代码。

using System.Collections;
using UnityEngine;

public class ARFingerGestures : MonoBehaviour
{
    public  Transform ARCamera; //AR相机拖拽到这个上面
    private float fingerActionSensitivity = Screen.width * 0.05f; //手指动作的敏感度,这里设定为 二十分之一的屏幕宽度.
    private float fingerBeginX;
    private float fingerBeginY;
    private float fingerCurrentX;
    private float fingerCurrentY;
    private float fingerSegmentX;
    private float fingerSegmentY;
    private int fingerTouchState;
    private int FINGER_STATE_NULL = 0;
    private int FINGER_STATE_TOUCH = 1;
    private int FINGER_STATE_ADD = 2;

    private Touch oldTouch1;  //上次触摸点1(手指1)  
    private Touch oldTouch2;  //上次触摸点2(手指2)

    

    float _最大缩放比例 = 1000f;
    float _最小缩放比例 = 0.2f;

    bool rot;
    //是否允许位移,默认打开,在双指触控时关闭,手指挪开时再打开
   // bool isOffset=true;
    Vector2 deltaPos;
    // private Vector3 offect;//偏移位置鼠标转世界坐标与transform.position的偏移量


    public enum GestureStatus
    {
        def,
        shrink,
        move
    }

    private GestureStatus gesStatus = GestureStatus.def;


    void Start()
    {
        fingerActionSensitivity = Screen.width * 0.05f;

        fingerBeginX = 0;
        fingerBeginY = 0;
        fingerCurrentX = 0;
        fingerCurrentY = 0;
        fingerSegmentX = 0;
        fingerSegmentY = 0;

        fingerTouchState = FINGER_STATE_NULL;
    }


    /// <summary>
    /// 双指平移
    /// </summary>
    /// <param name="arTarget"></param>
    /// <param name="arCamera"></param>
    Vector3 inputOffset;
    void ARGestureMove(Transform arTarget, Camera arCamera)
    {
        if (Input.GetTouch(1).phase == TouchPhase.Began)
        {
            Vector3 pos = arCamera.WorldToScreenPoint(arTarget.position);
            inputOffset = (Vector3)Input.GetTouch(1).position - pos;
        }
        if (gesStatus == GestureStatus.move)
        {
            if (Input.GetTouch(1).phase == TouchPhase.Moved)
            {   
                Vector3 point = arCamera.ScreenToWorldPoint((Vector3)Input.GetTouch(1).position - inputOffset);
                arTarget.position = GetPositonOnPlane(point, arCamera.transform.position, 0);
            }
        }
    }

    Vector3 GetPositonOnPlane(Vector3 point0, Vector3 cameraPos, float height)
    {
        if (point0.y == cameraPos.y || height == cameraPos.y || point0.y == height)
        {
            return point0;
        }
        float c = (height - point0.y) / (height - cameraPos.y);
        Vector3 result;
        result.x = (point0.x - c * cameraPos.x) / (1 - c);
        result.z = (point0.z - c * cameraPos.z) / (1 - c);
        result.y = height;
        return result;
    }
    // Update is called once per frame
    void Update()
    {

        //没有触摸  
        if (Input.touchCount <= 0)
        {
           // isOffset = true;
            return;
        }
        if (1 == Input.touchCount)
        {
            Touch touch = Input.GetTouch(0);
            deltaPos = touch.deltaPosition;

            if (Input.GetTouch(0).phase == TouchPhase.Began)
            {

                if (fingerTouchState == FINGER_STATE_NULL)
                {
                    fingerTouchState = FINGER_STATE_TOUCH;
                    fingerBeginX = Input.mousePosition.x;
                    fingerBeginY = Input.mousePosition.y;
                }

            }

            if (fingerTouchState == FINGER_STATE_TOUCH)
            {
                fingerCurrentX = Input.mousePosition.x;
                fingerCurrentY = Input.mousePosition.y;
                fingerSegmentX = fingerCurrentX - fingerBeginX;
                fingerSegmentY = fingerCurrentY - fingerBeginY;

            }
            if (fingerTouchState == FINGER_STATE_TOUCH && Input.GetTouch(0).phase == TouchPhase.Moved)
            {
                float fingerDistance = fingerSegmentX * fingerSegmentX + fingerSegmentY * fingerSegmentY;

                if (fingerDistance > (fingerActionSensitivity * fingerActionSensitivity))
                {
                    rot = true;
                }
            }

            if (Input.GetTouch(0).phase == TouchPhase.Ended)
            {
                fingerTouchState = FINGER_STATE_NULL;
                rot = false;
            }
        }
        if(Input.touchCount==2)
        {
            if (Input.GetTouch(1).phase==TouchPhase.Began)
                    {
                StartCoroutine(GesProcessing()); }
            ARGestureZoom();
            ARGestureMove(transform,Camera.main);
           

            if (Input.GetTouch(1).phase == TouchPhase.Ended)
                gesStatus = GestureStatus.def;
        }
        if (rot)
        {
            toAddFingerAction(deltaPos);
        }
    }
    public float num = 0;
    IEnumerator GesProcessing() {
        var touch0 = Input.GetTouch(0).position;
        var touch1 = Input.GetTouch(1).position;
        yield return new WaitForSeconds(0.1f);
        var dir0 = touch0 - Input.GetTouch(0).position;
        var dir1 = touch1 - Input.GetTouch(1).position;
        var angle = Vector3.Angle(dir0, dir1);
        Debug.Log("angle"+angle+"0"+dir0+"1"+dir1);
        if (angle < 15)
            gesStatus = GestureStatus.move;
        else
            gesStatus = GestureStatus.shrink;
    }
    private void ARGestureZoom() {
        //多点触摸, 放大缩小  
        Touch newTouch1 = Input.GetTouch(0);
        Touch newTouch2 = Input.GetTouch(1);

        //第2点刚开始接触屏幕, 只记录,不做处理  
        if (newTouch2.phase == TouchPhase.Began)
        {
            oldTouch2 = newTouch2;
            oldTouch1 = newTouch1;
            return;
        }
        if (gesStatus == GestureStatus.shrink)
        {
            //计算老的两点距离和新的两点间距离,变大要放大模型,变小要缩放模型  
            float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);
            float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);

            //两个距离之差,为正表示放大手势, 为负表示缩小手势  
            float offset = newDistance - oldDistance;

            //放大因子, 一个像素按 0.01倍来算(100可调整)  
            float scaleFactor = offset / (1000f / transform.localScale.x);
            Vector3 localScale = transform.localScale;

            Vector3 scale = new Vector3(localScale.x + scaleFactor,
                localScale.y + scaleFactor,
                localScale.z + scaleFactor);

            scale = new Vector3(Mathf.Clamp(scale.x, _最小缩放比例, _最大缩放比例),
                Mathf.Clamp(scale.y, _最小缩放比例, _最大缩放比例),
                Mathf.Clamp(scale.z, _最小缩放比例, _最大缩放比例));
            transform.localScale = scale;
            //最小缩放到 0.3 倍  
            //if (scale.x > _最小缩放比例 && scale.y > _最小缩放比例 && scale.z > _最小缩放比例)
            //{
            //	transform.localScale = scale;
            //}

            //记住最新的触摸点,下次使用  
            oldTouch1 = newTouch1;
            oldTouch2 = newTouch2;
        }
    }
    private void toAddFingerAction(Vector2 deltaPos)
    {

        fingerTouchState = FINGER_STATE_ADD;

        if (Mathf.Abs(fingerSegmentX) > Mathf.Abs(fingerSegmentY))
        {
            fingerSegmentY = 0;
        }
        else
        {
            fingerSegmentX = 0;
        }

        //上下旋转
        //if (fingerSegmentX == 0)
        //{
        //    if (fingerSegmentY > 0)
        //    {
        //        Debug.Log("up");
        //    }
        //    else
        //    {
        //        Debug.Log("down");
        //    }

        //    transform.Rotate(Camera.main.transform.right * deltaPos.y * 0.2f, Space.World);

        //}
        //左右旋转
        if (fingerSegmentY == 0)
        {
            if (fingerSegmentX > 0)
            {
                Debug.Log("right");
            }
            else
            {
                Debug.Log("left");
            }
            transform.Rotate(Vector3.down * deltaPos.x * 0.2f, Space.World);
        }

    }


}
  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值