• Unity3d android开发之触摸操作识别-双击,滑动去噪处理


      在android上开发unity游戏,和在IOS上差不多,但是还是有许多细微的差别的,这可能是由于系统或者硬件问题导致的差异吧,比较典型的就是-触摸屏上实现双击的差别。

      Unity3d 官方API文档上告诉我们一件事,http://docs.unity3d.com/Manual/MobileInput.html ,如图

      

      你看他说,IOS设备就可以通过tapcontrol来判断是否有双击产生,然而android设备并没有这个功能。原因不管,看到这里我们就知道了,要想判断双击事件,还得靠自己手动写代码实现了。其实,模仿windows的鼠标双击机制,我们完全可以利用已有的API对双击进行识别,比如单击后,先不进行单击操作,而是进行双击监测,监测0.1秒内是否又有新的触摸手指触摸到了屏幕,如果有,则认为整个时间连起来算一个双击,而忽略前面的单击,如果0.1秒过去,没有任何新的响应,我们就继续处理0.1秒前的单击时间,记得在进行双击监测前,保存下当初那一帧的数据,否则,0.1秒后,你再处理单击事件的时候,就物是人非了。

      废话不多说,直接上核心代码图

      

    if ( touchCount == 0 )        //手指没按屏幕或者松开
        {
            ResetControlState();
            
            if(typeOfOperation == E_OperationType.waitforDoubleTouch)        //在等待双击状态的0.1秒内,并没有手指按下,则认为刚才那个是单击
            {
                timeIntervalOfTouch = Time.time - fisrtTouchLeaveTime;    
                if(timeIntervalOfTouch >0.1)
                {
                    typeOfOperation = E_OperationType.noCommand;                                        
                    stateofmoving = E_MovingState.Continuous;    //启动持续行走模式
                    switchflag =1;
                    moving = true;
                }
            }    
            totalcount =0;    
        }
        else 
        {
            
            if(Input.GetTouch(0).phase == TouchPhase.Stationary )    //按住不放的状态下才算
                totalcount  += touchCount;        //如果持续按住不放,则累加,按照经验值,1秒钟可以累加50次
            
            
            var i : int;
            var touch : Touch;
            var theseTouches = Input.touches;
            
            var touch0 : Touch;
            var touch1 : Touch;
            var gotTouch0 = false;
            var gotTouch1 = false;        
            
            // Check if we got the first finger down
            if ( state == E_ControlState.WaitingForFirstTouch )        //手指按下的瞬间····
            {
                for ( i = 0; i < touchCount; i++ )
                {
                    touch = theseTouches[ i ];
            
                    if ( touch.phase != TouchPhase.Ended
                        && touch.phase != TouchPhase.Canceled )
                    {
                        state = E_ControlState.HandleFirstTouch;
                        firstTouchTime = Time.time;
                        fingerDown[ 0 ] = touch.fingerId;
                        fingerDownPosition[ 0 ] = touch.position;
                        fingerDownFrame[ 0 ] = Time.frameCount;
                        break;
                    }
                }
            }
            
            // Wait to see if a second finger touches down. Otherwise, we will
            // register this as a character move                    
            if ( state == E_ControlState.HandleFirstTouch )    //手指按下之后,一直处于这个状态
            {
                for ( i = 0; i < touchCount; i++ )
                {
                    touch = theseTouches[ i ];
    
                    if ( touch.phase != TouchPhase.Canceled )
                    {
                        if ( touchCount == 1 )        //依然是一个手指
                        {
                        //    var deltaSinceDown = touch.position - fingerDownPosition[ 0 ];
                            
                            // Either the finger is held down long enough to count
                            // as a move or it is lifted, which is also a move. 
                            if ( touch.fingerId == fingerDown[ 0 ]  )
                            {
                                if(touch.phase == TouchPhase.Ended)    //手指离开的瞬间启动
                                {
                                    if(maxmovecount >5)
                                    {
                                        typeOfOperation = E_OperationType.slidingtouch;        //滑动触摸单击
                                        state = E_ControlState.WaitingForFirstTouch;
                                        maxmovecount =0;
                                    }
                                    else
                                    {
                                        timeOfFingerStay =Time.time - firstTouchTime;        //计算手指停留的时间
                                        if(timeOfFingerStay > doubleTouchTimeLimit)        //手指停留时间大于双击时限算一次单击
                                        {
                                            if(typeOfOperation !=E_OperationType.singleTouched)
                                                typeOfOperation = E_OperationType.singleTouched;                                        
                                            state = E_ControlState.MovingCharacter;
                                        }
                                        else{        //手指停留时间小于双击时限,则认为有可能发生双击,此时要检测若干时间内是否再有手指按下,无手指按下,则按单击处理
                                            
                                            if(typeOfOperation !=E_OperationType.waitforDoubleTouch && typeOfOperation !=E_OperationType.doubleTouched)
                                            {
                                                typeOfOperation = E_OperationType.waitforDoubleTouch;
                                                fisrtTouchLeaveTime = Time.time;        //记下手指离开的时间,以便计算下次再按的时候的时间间隔
                                                state = E_ControlState.WaitingForFirstTouch;
                                            }
                                        }
                                    }
                                    
                                    //根据状态做出响应
                                    OnSingleTouchEnd();
                                        
                                    
                                } 
                                
                                if(touch.phase ==TouchPhase.Began && typeOfOperation ==E_OperationType.waitforDoubleTouch)
                                {
                                    timeIntervalOfTouch = Time.time - fisrtTouchLeaveTime;    //计算两次touch的间隔时间,间隔时间小于0.2秒,则认为是双击
                                    if(timeIntervalOfTouch < 0.2)
                                        typeOfOperation = E_OperationType.doubleTouched;
                                    state = E_ControlState.WaitingForFirstTouch;
                                }
                                if(touch.phase == TouchPhase.Moved)
                                {
                                    maxmovecount +=1;
                                }
                                if(touch.phase == TouchPhase.Stationary)
                                {
                                    timeOfFingerStay =Time.time - firstTouchTime;        //计算手指停留的时间
                                    if(timeOfFingerStay >0.3 && (stateofmoving == E_MovingState.Continuous))    //如果手指停留超0.3秒,且处于持续行走状态,则立马静止
                                    {
                                        stateofmoving = E_MovingState.SuddenlyStop;
                                        moving = false;
                                    }
                                }
                                break;
                            }                            
                        }
                    }
                }
            }
            
            
    
        }
    View Code

      说完双击,咱们来说说滑动处理,其实滑动处理挺好处理的,就是读取touch.phase而已嘛,但是,要知道用户的操作都是有一定的噪声的,比如一些抖动之类的,底层的物理层帮我们处理的是细微的振动噪声和热噪声,而我们上层应用开发者需要处理的,就是人的操作噪声,比如说,我按住不放的时候,手抖了,这算是滑动还是按住不放的动作呢?也许你觉得这是一个不起眼的细节,然而对用户体验要求越来越高的现在,操作上的细节实际上就决定了一个游戏的成败,你的容错性较好,对细节处理的很好,那么将来游戏做好了,玩家玩得会比较舒服。假如你认为用户要来适应你得程序来进行操作适应的话,我想这个还是等你们的平台足够大了的时候再说吧。

      

  • 相关阅读:
    中断向量表
    lua绑定C++对象—luna模板
    lua对象调用—用 "." 与 ":" 调用表中函数时的区别
    FreeSWITCH 实现 双线路呼叫(主备线路)
    [转]Freeswitch在阿里云服务器语音不通问题小记(FS的NAT穿越穿透)
    [转]签发使用自签发证书--指定使用多域名、泛域名及直接使用IP地址
    [转]FreeSwitch启用WEBRTC小记
    [转]FreeSwitch1.10版本安装及内置mariadb(mysql)使用记录
    FreeSWITCH 使用 lua 脚本 接管 分机注册,鉴权等
    sip客户端NAT注册和拨打FreeSWITCH ,FreeSWITCH 会发到 sip客户端内网地址的问题
  • 原文地址:https://www.cnblogs.com/pengsy/p/4703585.html
Copyright © 2020-2023  润新知