Unity AR应用中常用到的输入方式

Ian Failes 2017-09-11 15:36:10

原标题:Unity AR应用中常用到的输入方式

笔者最近做AR项目的时候,因为不想用外部控制插件,所以研究了下unity原生的移动端输入方式,这些是Unity AR应用中常用到的输入方式,InputTouch贴上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyTouch : MonoBehaviour
{
    /// <summary>
    /// 定义的一个手指类
    /// </summary>
    private class MyFinger
    {
        public int id = -1;
        public Touch touch;

        static private List<MyFinger> fingers = new List<MyFinger>();

        /// <summary>
        /// 手指容器
        /// </summary>
        static public List<MyFinger> Fingers
        {
            get
            {
                if (fingers.Count == 0)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        MyFinger mf = new MyFinger();
                        mf.id = -1;
                        fingers.Add(mf);
                    }
                }
                return fingers;
            }
        }
    }

    // 小圈圈:用来实时显示手指触摸的位置
    private GameObject[] marks = new GameObject[5];

    public GameObject markPerfab = null;

    // 粒子效果:来所显示手指手动的大概路径
    private ParticleSystem[] particles = new ParticleSystem[5];

    public ParticleSystem particlePerfab = null;

    //单手指移动模型
    public float speed = 2f;

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

    private void Start()
    {
        for (int i = 0; i < MyFinger.Fingers.Count; i++)
        {
            GameObject mark = Instantiate(markPerfab, Vector3.zero, Quaternion.identity) as GameObject;
            mark.transform.parent = this.transform;
            mark.SetActive(false);
            marks = mark;

            ParticleSystem particle = Instantiate(particlePerfab, Vector3.zero, Quaternion.identity) as ParticleSystem;
            particle.transform.parent = this.transform;
            particle.Pause();
            particles = particle;
        }
    } //初始化模型和特效

    private void Update()
    {
        Touch[] touches = Input.touches;

        // 遍历所有的已经记录的手指
        // --掦除已经不存在的手指
        foreach (MyFinger mf in MyFinger.Fingers)
        {
            if (mf.id == -1)
            {
                continue;
            }
            bool stillExit = false;
            foreach (Touch t in touches)
            {
                if (mf.id == t.fingerId)
                {
                    stillExit = true;
                    break;
                }
            }
            // 掦除
            if (stillExit == false)
            {
                mf.id = -1;
            }
        }
        // 遍历当前的touches
        // --并检查它们在是否已经记录在AllFinger中
        // --是的话更新对应手指的状态,不是的放放加进去
        foreach (Touch t in touches)
        {
            bool stillExit = false;
            // 存在--更新对应的手指
            foreach (MyFinger mf in MyFinger.Fingers)
            {
                if (t.fingerId == mf.id)
                {
                    stillExit = true;
                    mf.touch = t;
                    break;
                }
            }
            // 不存在--添加新记录
            if (!stillExit)
            {
                foreach (MyFinger mf in MyFinger.Fingers)
                {
                    if (mf.id == -1)
                    {
                        mf.id = t.fingerId;
                        mf.touch = t;
                        break;
                    }
                }
            }
        }

        // 记录完手指信息后,就是响应相应和状态记录了
        for (int i = 0; i < MyFinger.Fingers.Count; i++)
        {
            MyFinger mf = MyFinger.Fingers;
            if (mf.id != -1)//有手指
            {
                if (Input.touchCount == 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
                {
                    Vector3 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
                    transform.Translate(-touchDeltaPosition.x * speed, touchDeltaPosition.y * speed, 0);
                }

 

                //多点触摸, 放大缩小
                Touch newTouch1 = Input.GetTouch(0);
                Touch newTouch2 = Input.GetTouch(1);

                //第2点刚开始接触屏幕, 只记录,不做处理
                if (newTouch2.phase == TouchPhase.Began)
                {
                    oldTouch2 = newTouch2;
                    oldTouch1 = newTouch1;
                    return;
                }

                //计算老的两点距离和新的两点间距离,变大要放大模型,变小要缩放模型
                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 / 100f;
                Vector3 localScale = transform.localScale;
                Vector3 scale = new Vector3(localScale.x + scaleFactor,
                        localScale.y + scaleFactor,
                        localScale.z + scaleFactor);

                //最小缩放到 0.3 倍
                if (scale.x > 0.3f && scale.y > 0.3f && scale.z > 0.3f)
                {
                    transform.localScale = scale;
                }

                //记住最新的触摸点,下次使用
                oldTouch1 = newTouch1;
                oldTouch2 = newTouch2;

                if (mf.touch.phase == TouchPhase.Began)//开始
                {
                    marks.SetActive(true);
                    marks.transform.position = GetWorldPos(mf.touch.position);

                    particles.transform.position = GetWorldPos(mf.touch.position);
                }
                else if (mf.touch.phase == TouchPhase.Moved)//移动
                {
                    marks.transform.position = GetWorldPos(mf.touch.position);

                    if (!particles.isPlaying)
                    {
                        particles.loop = true;
                        particles.Play();
                    }
                    particles.transform.position = GetWorldPos(mf.touch.position);
                }
                else if (mf.touch.phase == TouchPhase.Ended)//结束
                {
                    marks.SetActive(false);
                    marks.transform.position = GetWorldPos(mf.touch.position);

                    particles.loop = false;
                    particles.Play();
                    particles.transform.position = GetWorldPos(mf.touch.position);
                }
                else if (mf.touch.phase == TouchPhase.Stationary)//放下但没动
                {
                    if (particles.isPlaying)
                    {
                        particles.Pause();
                    }
                    particles.transform.position = GetWorldPos(mf.touch.position);
                }
            }
            else //没有手指
            {
                ;
            }
        }

        // exit
        if (Input.GetKeyDown(KeyCode.Home) || Input.GetKeyDown(KeyCode.Escape))
        {
            Application.Quit();
        }

        // 测试点击生成特效
        //     if (Input.GetMouseButtonDown(0))
        //     {
        //         GameObject mark = Instantiate(markPerfab, Vector3.zero, Quaternion.identity) as GameObject;
        //         mark.transform.parent = this.transform;
        //         mark.transform.position = GetWorldPos(Input.mousePosition);
        //
        //         ParticleSystem particle = Instantiate(particlePerfab, Vector3.zero, Quaternion.identity) as ParticleSystem;
        //         particle.transform.parent = this.transform;
        //         particle.transform.position = GetWorldPos(Input.mousePosition);
        //         particle.loop = false;
        //         particle.Play();
        //      }
    }

    /// <summary>
    /// 显示相关手指数据
    /// </summary>
    private void OnGUI()
    {
        GUILayout.Label("支持的手指的数量:" + MyFinger.Fingers.Count);
        GUILayout.BeginHorizontal(GUILayout.Width(Screen.width));
        for (int i = 0; i < MyFinger.Fingers.Count; i++)
        {
            GUILayout.BeginVertical();
            MyFinger mf = MyFinger.Fingers;
            GUILayout.Label("手指" + i.ToString());
            if (mf.id != -1)
            {
                GUILayout.Label("Id: " + mf.id);
                GUILayout.Label("状态: " + mf.touch.phase.ToString());
            }
            else
            {
                GUILayout.Label("没的发现!");
            }
            GUILayout.EndVertical();
        }
        GUILayout.EndHorizontal();
    }

    public Vector3 GetWorldPos(Vector2 screenPos)
    {
        return Camera.main.ScreenToWorldPoint(new Vector3(screenPos.x, screenPos.y, Camera.main.nearClipPlane + 10));
    }
}

99VR视界二维码
热门推荐
Hot Recommended
在线客服