一种Unity里的多点触控处理方法

本文介绍了一个用于Unity游戏开发的自定义触屏输入管理组件。该组件支持多点触控,并通过封装常用的输入操作简化了游戏开发过程。文章详细解释了如何初始化组件并配置触控区域,展示了如何处理触控开始、移动及结束事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
大家好,我感觉到游戏开发中有许多相通的共性,如动画,特效,声音,输入,文件,网络等。其中
逻辑部分可以自己想,动画、特效、声音等依赖资源,输入部分处理依赖平台API,网络也要依赖平台API。
平台与平台之间有很大的差异性,一般来说一个平台的软件不能放到不同CPU的平台上直接运行,为此,产
生了JAVA、C#、Lua等脚本语言,依赖于要执行的平台安装运行脚本语言的环境。另外一种解决办法,是源
代码的重新编译,让编译器可以针对不同的平台编译出不同的二进制代码。于是,跨平台C++,网络方面
POSIX Socket产生了。游戏引擎使用上面两种方式一种或两种就能实现跨平台编译运行。
我深知时间的宝贵,为了提高开发效率,有必要用已学的知识写出可以通用的代码,方便以后再次使用。
为了实现这个目标,需要有扎实的基本功,写出耦合性几乎没有的组件。
Unity是组件式开发,我打算尝试着开发一套自己的包装类,用来封装经常用到的游戏功能。
我打算先从最简单的输入着手,以后再做动画、网络部分等,敬请期待。
输入部分分触屏操作与鼠标、键盘操作,此为触屏操作。
触屏调试可以安装unity Remote 5
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
多点触控时系统返回的触摸点个数会变,位置会变,为了能够承接上一个状态判断移动的开始点与现在的点,继而得到向量,我
保存了beginpositions数组为开始点,对应的nowpositions为开始的点移动到了现在的点,touchyunxucha(touch允许差让我们
判定新得到的点是否是上一状态的某点的变化)
*/
public class TouchControl : MonoBehaviour {
    public int fingers = 1;                          //支持几点触控
    public static TouchControl instance = null;      //单例
    private float windowwidth;                       //窗口宽,默认为全屏
    private float windowheight;                      //窗口高,默认为全屏
    private Vector2 []beginpositions;                //点击事件开始位置 
    private Vector2 []nowpositions;                  //与beginPositions对应的当前移动到的位置
    public Vector2 []movedirection;                  //供外界判断使用的移动向量,为nowPositon - beginPositon
    public bool []istouching;                        //对应beginpositions里的点判断是否有效
    private Rect[] fingerrects;                            //对应beginpositions点击的范围
    private bool allout = true;                      //判断是否没有点在点击区域
    public float touchyunxucha = 0.1f;               //在touchmoving的点与上一次的误差在此范围内视为同一点的移动
    public delegate void processTouchBeginPosition(int index,Vector2 beginpos);//可以为点击开始添加特效
    public delegate void processTouchMovePosition(int index,Vector2 beginpos,Vector2 movepos);//可以为点击移动添加特效
    public delegate void processTouchEndPosition(int index,Vector2 endpos);//可以为点击结束添加特效
    public delegate void processNoTouch();//可以为点击结束添加特效
    public processTouchBeginPosition processtouchbegin;
    public processTouchMovePosition processtouchmove;
    public processTouchEndPosition processtouchend;
    public processNoTouch processnotouch;
    public bool isinit = false;
    public bool isuichecked = false;
    void setBasicValues()
    {
        windowwidth = Screen.width;
        windowheight = Screen.height;
        beginpositions = new Vector2[fingers];            //最多支持fingers点触控
        nowpositions = new Vector2[fingers];
        movedirection = new Vector2[fingers];
        istouching = new bool[fingers];
        for(int i = 0 ; i < fingers; i++)
        {
            istouching[i] = false;
        }
        fingerrects = new Rect[fingers] ;
    }
    public bool setFingerArea(int index,Rect rect)//此处rect为窗口的比例
    {
        if (index >= fingers || index < 0)
            return false;
        fingerrects[index] = rect;
        return true;
    }
    // Use this for initialization
    void Awake()
    {
        instance = this;
        this.enabled = false;
    }
    void Start() {
        setBasicValues();
        Input.multiTouchEnabled = true;//开启多点触碰
        isinit = true;
    }
    public bool OutOfControlRect(Vector2 pos)
    {
        for(int i = 0;i < fingers; i++)
        {
            if (fingerrects[i].Contains(pos))
                return false;
        }
        return true;
    }
    // Update is called once per frame
    void Update () {
        if (Input.touchCount < 1)               //没有点击时istouching全为false
        {
            for (int i = 0; i < fingers; i++)
            {
                istouching[i] = false;      
            }
            if (!isuichecked)
            {
                processnotouch();
            }
            return;
        }
        
        for (int i = 0; i < Input.touchCount; i++)
        {
           
            var temp = new Vector2(Input.touches[i].position.x / windowwidth, Input.touches[i].position.y / windowheight); //点击处转换为屏幕的比例点
            if (Input.touches[i].phase == TouchPhase.Began)     //要处理的点击为TouchPhase.Began时处理方法
            {
                for (int j = 0;j < fingers;j++)
                {
                    if( fingerrects[j].Contains(temp))
                    {
                  
                            Debug.Log("touch begin");
                            beginpositions[j] = nowpositions[j] = temp;
                            processtouchbegin(j, temp);
                            isuichecked = false;
                            istouching[j] = true;
                            allout = false;
                        
                    }
                }
            }
            if (Input.touches[i].phase == TouchPhase.Moved)    //要处理的点击为TouchPhase.Moved时处理方法
            {
                for(int j = 0;j < fingers;j++)
                {
                    if(istouching[j] && Vector2.Distance(nowpositions[j],temp) <= touchyunxucha)
                    {
                        nowpositions[j] = temp;
                        processtouchmove(j,beginpositions[j],temp);
                        isuichecked = false;
                    }
                }
            }
            if (Input.touches[i].phase == TouchPhase.Ended)    //要处理的点击为TouchPhase.Ended时处理方法
            {
                for(int j = 0;j < fingers;j++)
                {
                    if (istouching[j] && Vector2.Distance(nowpositions[j], temp) <= touchyunxucha)
                    {
                        istouching[j] = false;
                        processtouchend(j, temp);
                        isuichecked = false;
                    }


                }
            }
        }
        for(int i = 0;i < fingers;i++)
        {
            if(istouching[i])
            {
                movedirection[i] = nowpositions[i] - beginpositions[i];
                
            }
        }
     
    }
}






/*
虽然很想什么都不做就用本组件,但实际应用中按钮有千差万别,所以还是要初始化本类来正常使用。
要使用本类请把本类挂到任意一个Unity组件上,建议拖到摄像机上。接下来,要对本类进行初始化,以得到正确的表现方式。
具体如:
1.设置fingers整形,为处理的最多点数
2.设置每个fingerrects,从0到fingers-1下标
*/
/*
以下为使用本脚本的示例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class test : MonoBehaviour {
    TouchControl tc;
// Use this for initialization
    IEnumerator waitForTouchControlInit()
    {
        while (!tc.isinit)
        {
            yield return null;
        }
        tc.setFingerArea(0, new Rect(0, 0, 0.3f, 0.3f));
        tc.setFingerArea(1, new Rect(0.7f, 0, 0.3f, 0.3f));


    }
    void processTouchBeginPosition(int index, Vector2 beginpos)
    {
        Debug.Log("显示触控球与小球在位置" + beginpos.ToString());
    }
    void processTouchMovePosition(int index, Vector2 beginpos, Vector2 movepos)
    {
        Debug.Log("显示小球在位置" + movepos.ToString());
        Debug.Log("按钮index为:" + index + "按钮移动向量为" + tc.movedirection[index]);
    }
    void processTouchEndPosition(int index, Vector2 endpos)
    {
        Debug.Log("隐藏编号为index触控球与小球" + endpos.ToString());
    }
    void processNoTouch()
    {
        Debug.Log("把显示的触控UI检查一下防止还有意外留下的按钮图片");
        tc.isuichecked = true;
    }
    void Start () {
        tc = TouchControl.instance;//Camera.main.GetComponent<TouchControl>();
        tc.fingers = 2;
        tc.enabled = true;
        StartCoroutine(waitForTouchControlInit());
        tc.processtouchbegin += processTouchBeginPosition;
        tc.processtouchmove += processTouchMovePosition;
        tc.processtouchend += processTouchEndPosition;
        tc.processnotouch += processNoTouch;
    }

// Update is called once per frame
void Update () {

}
}


*/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值