首页 > 解决方案 > Unity:使用 TouchPhase.Moved 时如何停止读取第一次触摸

问题描述

我有两个脚本一个是播放器控制器:

void Update () {
   if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    {


        Touch touch = Input.GetTouch(0);
        Ray ray = cam.ScreenPointToRay(touch.position);
        RaycastHit hit;

        if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
        {
            return;
        }


        if (Physics.Raycast(ray, out hit, 100))
        {

            Interactable interactable = hit.collider.GetComponent<Interactable>();
             if (interactable != null)
             {
                SetFocus(interactable);
             }
             else
             {
                motor.MoveToPoint(hit.point);

                RemoveFocus();
            }

        }
    }
}       

然后我的相机脚本是:

void Update()
{
    currentZoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
    currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);

    currentYaw -= Input.GetAxis("Horizontal") * yawSpeed * Time.deltaTime;
    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
    {
        Vector2 touchDirection = Input.GetTouch(0).deltaPosition;
        if (touchDirection.x > minSwipe || touchDirection.x < -minSwipe)
        {
            currentYaw -= touchDirection.x * yawSpeed / mobileYawReduction * Time.deltaTime;
        }

    }
}

// Update is called once per frame
void LateUpdate () {
    transform.position = target.position - offset * currentZoom;
    transform.LookAt(target.position + Vector3.up * pitch);

    transform.RotateAround(target.position, Vector3.up, currentYaw);
}

这两个都很好:我可以通过点击移动我的角色并在滑动时很好地旋转相机,唯一的问题是当我滑动旋转时,它会记录触摸的开始并开始移动。我将如何避免这种情况?

标签: c#unity3dmobile

解决方案


而不是在触摸开始时移动,您只能在触摸结束时移动,并且在触摸期间触摸位置没有太大变化。

如果正在触摸并且位置变化超过一点阈值,则将其解释为滑动并在触摸结束时跳过调用目标代码块。

// if movement was greater than interpret as swipe 
public float swipeThreshold = 0.01;

Vector2 startPosition ;
float movedDistance;

Touch touch;

void Update () 
{
    if (Input.touchCount <= 0) return;

    switch(Input.GetTouch(0).phase)
    {
        case TouchPhase.Began:
            // On begin only save the start position

            touch = Input.GetTouch(0);

            if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
            {
                return;
            }

            startPosition = touch.position;
            movedDistance = 0;
            break;

        case TouchPhase.Moved:
            // if moving check how far you moved

            movedDistance = Vector2.Distance(touch.position, startPosition );
            break;

        case TouchPhase.Ended:
            // on end of touch (like button up) check the distance
            // if you swiped -> moved more than swipeThreshold
            // do nothing

            if(movedDistance > swipeThreshold) break;

            Ray ray = cam.ScreenPointToRay(touch.position);
            RaycastHit hit;
            if (!Physics.Raycast(ray, out hit, 100)) break;

            Interactable interactable = hit.collider.GetComponent<Interactable>();
            if (interactable != null)
            {
                SetFocus(interactable);
            }
            else
            {
                motor.MoveToPoint(hit.point);
                RemoveFocus();
            }
            break;

        default:
            break;
    }
}

我会在相机脚本中添加相同的阈值以保持一致。要么在它们之间以某种方式共享此阈值(甚至从另一个脚本中获取),要么简单地放入相同的值

public float swipeThreshold = 0.01;

Vector2 startPosition;

void Update()
{
    currentZoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
    currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);

    currentYaw -= Input.GetAxis("Horizontal") * yawSpeed * Time.deltaTime;

    if (Input.touchCount <= 0) return;

    switch(Input.GetTouch(0).phase)
    {
        case TouchPhase.Began:
            startPosition = Input.GetTouch(0).position;
            break;

        case TouchPhase.Moved:
            // if yet not moved enough do nothing
            var movedDistance = Vector2.Distance(Input.GetTouch(0).position, startPosition);
            if (movedDistance <= swipeThreshold) break;

            Vector2 touchDirection = Input.GetTouch(0).deltaPosition;
            if (touchDirection.x > minSwipe || touchDirection.x < -minSwipe)
            {
                currentYaw -= touchDirection.x * yawSpeed / mobileYawReduction * Time.deltaTime;
            }
            break;

        default:
            break;
    }
}

推荐阅读