网站公告 | 泰斗网校全新上线了,可以和论坛用户登录同步,如果遇到登录问题联系管理员解决
查看: 5412|回复: 16
收起左侧

[Unity3d] 【新手求助】如何分辨“点击”和“拖动”两种不同的操作

[复制链接]

[Unity3d] 【新手求助】如何分辨“点击”和“拖动”两种不同的操作[复制链接]

红莉栖 发表于 2017-10-18 22:20:58 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  15 浏览:  5412
50泰斗币
如题,
目前,我的方法是:

Input.GetTouch(0).deltaPosition 获得手指移动量

在TouchPhase.Ended的时候判断,
如果移动量小于某个值,就认为是点击操作,

在TouchPhase.Moved时候也判断,
如果移动量大于某个值,就判断为拖动操作。


[C#] 纯文本查看 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/*这个脚本绑定在TiledMap组件所在场景的主摄像机上*/

public class TileMapCameraCtrl : MonoBehaviour {

    public Boolean IsCameraMoving; //当前是否正在移动摄像机(且没有完成)

    public float CameraMoveSpeed = 300f;
    public float TouchSpeed = 8f;

    private bool isDrag = true;

    // Use this for initialization
    void Start () {

	}
	
	// Update is called once per frame
	void Update ()
    {
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);
            switch (touch.phase)
            {
                //拖动阶段结束时:
                case TouchPhase.Ended:
                    if (isDrag == true)
                    {
                        isDrag = false;
                        return;
                    }
                    //拖动结束
                    else
                    {
                        //获得变化量
                        Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
                        //如果变化量小于指定值,判断为点击
                        if (-4<touchDeltaPosition.x && touchDeltaPosition.x<4 && touch.phase != TouchPhase.Moved)
                        {
                            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                            RaycastHit hit;
                            if (Physics.Raycast(ray, out hit))
                            {
                                if (hit.transform.gameObject.tag == "Ground")
                                {
                                    ClickableTile CT = hit.transform.gameObject.GetComponent<ClickableTile>();
                                    CT.ClickableTileOnClicked();
                                }
                            }
                        }
                    }
                    break;
                //拖动阶段中
                case TouchPhase.Moved:
                    isDrag = true;
                    //获得变化量
                    Vector2 touchedDeltaPosition = Input.GetTouch(0).deltaPosition;
                    //判断距离是否足以移动,如果是,才移动
                    if (touchedDeltaPosition.x<-4 || touchedDeltaPosition.x>4)
                    {
                        float xMove = 0;
                        //float yMove = 0;
                        if (touchedDeltaPosition.x < -4)
                            xMove = 1;
                        else if (touchedDeltaPosition.x > 4)
                            xMove = -1;
                        /*
                        if (touchedDeltaPosition.y < -5)
                            yMove = 1;
                        else if (touchedDeltaPosition.y > 5)
                            yMove = -1;
                        */
                        transform.Translate(new Vector3(xMove,0,0) * TouchSpeed * Time.deltaTime);
                    }
                    break;
            }
        }

    }

    //对齐寻路单位的位置
    public void CameraOnPathFindAgent(string AgentName)
    {
        //Debug.Log("");
        //获取Agent坐标:
        Vector3 AgentPosition = GameObject.FindGameObjectWithTag(AgentName).transform.position;
        iTween.MoveTo(Camera.main.gameObject, iTween.Hash(
         "x", AgentPosition.x,
         "y", AgentPosition.y,
         "time", 1.2f,
         "oncompletetarget", this.gameObject,
         "oncomplete", "CameraMoveComplete"
        ));
    }

    //摄像机移动完毕,重置变量
    void CameraMoveComplete()
    {
        Debug.Log("MoveComplete");
        IsCameraMoving = false;
    }
}


出现的问题是
当拖动时很容易出发点击操作
不太清楚问题出在哪里,不知是否可用触摸更新间隔来判断
求解决思路,多谢。

最佳答案

查看完整内容

[md]有几个问题。 首先用deltaPosition应该很难达到你的需求,看下官方的说明文档: > ### Touch.deltaPosition > > public Vector2 deltaPosition; > ### Description > > The position delta since last change. > > The absolute position of the touch is recorded periodically and available in the position property. The deltaPosition value is a Vector2 that represents the **difference between the touch posi ...
+1
5419°C
15
  • younglee
  • 红莉栖
  • 泰课_robin
  • 泰课_robin
  • DADA011
过: 他们
因分享而快乐,学习以自强!
younglee 发表于 2017-10-18 22:20:59 显示全部楼层

有几个问题。

首先用deltaPosition应该很难达到你的需求,看下官方的说明文档:

Touch.deltaPosition

public Vector2 deltaPosition;

Description

The position delta since last change.

The absolute position of the touch is recorded periodically and available in the position property. The deltaPosition value is a Vector2 that represents the difference between the touch position recorded on the most recent update and that recorded on the previous update.

我特意标黑了关键部分,可以看到这个属性获取到的是两帧之间的触摸点偏移量,如果帧率足够快,这个值将会非常小,所以基本上达不到你的过滤条件,从而很难实现“拖动”操作。

其次每当有偏移,你的isDrag属性都会被置为true,根据你的逻辑,这样即无法检测为click事件。只有按下和抬起手指无任何偏移才会触发click。问题在于,当屏幕的分辨率较大,手指触摸操作很难做到完全0偏移,则这样的逻辑会导致真正的click操作也不太好触发。

综上,实际上你的代码会过滤掉大部分click和drag操作,尤其是屏幕分辨率很高时,很可能你会发现滑动手指时,你定义的两种操作都不会触发。

有一种应该可行的修改方案,是不采用帧间偏移量,而是记下按下时的位置和抬起的位置,计算插值来判断。

点评

相当棒~~~  发表于 2017-10-20 21:09

评分

参与人数 2泰斗币 +11 热心值 +1 收起 理由
红莉栖 + 1 + 1 甚好!
Recote + 10 很给力!

查看全部评分

因分享而快乐,学习以自强!
红莉栖
 楼主|
发表于 2017-10-18 22:21:55 显示全部楼层
//对齐寻路单位的位置 这个函数跟本次的问题是没有关系的,可以不看。
因分享而快乐,学习以自强!
泰课_robin 发表于 2017-10-19 09:09:42 显示全部楼层
你是基于移动量来区别是点击还是move,这样就有问题啊。如果你在拖动时移动量小,就又触发点击了。
如果你基于是否有物体是选中状态来区别点击,就可以了。
[C#] 纯文本查看 复制代码
void Update()
{
   //有触摸事件发生继续
   if(Input.touchCount > 0) 
   {
       //获取第一个触摸事件
       Touch th = Input.GetTouch(0);
       //判断为触摸开始
       if (th.phase == TouchPhase.Began) 
       {
           //获取触摸点生成射线
           Ray ray = Camera.main.ScreenPointToRay(new Vector3(th.position.x, th.position.y, 0));
           RaycastHit hit;
           if(Physics.Raycast(ray, out hit, 1000))
           {
               //得到射线碰到的物体,即触摸时应该选中的物体
               GameObject obj = hit.transform.gameObject;
               //如果选中的是本物体
               if(obj.Equals(gameObject))
               {
                   IsSelected = true;
                   gameObject.SetActive(true);
               }
           }
       }
       //判断为移动
       if (th.phase == TouchPhase.Moved && IsSelected) 
       {
           //移动本物体
           Vector3 position_Move = new Vector3(th.deltaPosition.x, 0, th.deltaPosition.y) * 10;
           transform.position += position_Move;
       }
       //判断为触摸结束
       if(th.phase == TouchPhase.Ended && IsSelected) 
       {
           IsSelected = false;
           gameObject.SetActive(false);
       }
   }
}
因分享而快乐,学习以自强!
泰课_robin 发表于 2017-10-19 09:12:45 显示全部楼层
这只是一个示例,不一定适用你的情况,但道理是差不多的。如果有物体是选中状态,那就算有比较小的移动量,照样不判断为点击
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:34:27 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:34:57 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:35:14 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:35:32 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:35:50 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:36:12 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:36:31 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:36:55 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
DADA011 发表于 2017-10-23 15:37:29 显示全部楼层
因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
星陨尘心_clw 发表于 2017-11-2 10:57:19 显示全部楼层

因分享而快乐,学习以自强!
因分享而快乐,学习以自强!
12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 浙ICP 备 13006852号-15 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.4

1
QQ