如何在Unity中有效区分点击和滑动?

时间:2019-07-06 09:13:33

标签: c# android unity3d swipe tap

这是我第一次尝试在Unity中制作带有触摸控件的手机游戏。我基本上可以正常工作了。但是有一个问题,如何清楚地表明滑动不是轻拍?

我在教程中部分发现的代码的工作方式是,注册一个水龙头,我看用户是否在最短时间内静止了触摸屏(在这种情况下为0.05秒)。对于滑动,我查看用户的触摸是否在最小距离范围内移动。

问题在于,由于用户在0.05秒内没有移动手指,所以轻扫的开始通常会记录为轻击。我可以简单地增加注册一次点击的最小静止时间,但这意味着从用户点击屏幕到执行动作之间,游戏会有更多的延迟...

我的问题是否有完美的解决方案?在移动游戏《雷曼历险记》中,水龙头使玩家跳动并滑动即可更改其方向,并且运行十分流畅,当您尝试改变方向时,只有极少数情况下玩家会跳动。我不知道他们是如何工作的。

提前感谢您的时间!

这是我的代码:

    public static event Action<SwipeData> OnSwipe = delegate { };
    public static event Action OnTap = delegate { };

    [Header("Swipe parameters")]
    [SerializeField]
    bool m_DetectSwipeOnlyAfterRelease;
    [SerializeField]
    float m_MinDistanceForSwipe;

    [Header("Tap parameters")]
    [SerializeField]
    float m_TapTimeMinThreshold;

    private Vector2 m_FingerDownPosition;
    private Vector2 m_FingerUpPosition;

    private float m_TouchTime;
    private bool m_StationaryTouch;
    private bool m_TapRegistered;
    private bool m_SwipeRegistered;

    void Start() {
        m_TapRegistered = true;
        m_SwipeRegistered = true;
    }

    void Update() {
        if (Input.touchCount == 1) {
            Touch touch = Input.GetTouch(0);
            if (touch.phase == TouchPhase.Began) {
                m_FingerUpPosition = touch.position;
                m_FingerDownPosition = touch.position;
                m_TouchTime = Time.time;
                m_StationaryTouch = true;
                m_TapRegistered = false;
                m_SwipeRegistered = false;
            }

            if(!m_SwipeRegistered && touch.phase == TouchPhase.Moved) {
                m_StationaryTouch = false;
                m_FingerDownPosition = touch.position;
                SwipeDirection swipeDirection = DetectSwipe();
                // If a swipe was registered
                if (!swipeDirection.Equals(SwipeDirection.NONE)) {
                    // And it was horizontal, we reset the swipe detection
                    if (swipeDirection.Equals(SwipeDirection.LEFT) || swipeDirection.Equals(SwipeDirection.RIGHT))
                        m_FingerUpPosition = touch.position;
                    else
                        m_SwipeRegistered = true;
                }
            }

            // If the touch was stationary for the min threshold amount of time we register it as a tap
            if (m_StationaryTouch && !m_TapRegistered && Time.time - m_TouchTime > m_TapTimeMinThreshold) {
                m_TapRegistered = true;
                OnTap();
            }

            if (!m_SwipeRegistered && touch.phase == TouchPhase.Ended && !m_TapRegistered) {
                m_FingerDownPosition = touch.position;
                DetectSwipe();
            }
        }
    }

    private SwipeDirection DetectSwipe() {
        if (SwipeDistanceCheckMet()) {
            SwipeDirection direction;
            if (IsVerticalSwipe()) {
                direction = m_FingerDownPosition.y - m_FingerUpPosition.y > 0 ? SwipeDirection.UP : SwipeDirection.DOWN;
                SendSwipe(direction);
            }
            else {
                direction = m_FingerDownPosition.x - m_FingerUpPosition.x > 0 ? SwipeDirection.RIGHT : SwipeDirection.LEFT;
                SendSwipe(direction);
            }
            m_FingerUpPosition = m_FingerDownPosition;
            return direction;
        }
        return SwipeDirection.NONE;
    }

    private bool IsVerticalSwipe() {
        return VerticalMovementDistance() > HorizontalMovementDistance();
    }

    private bool SwipeDistanceCheckMet() {
        return VerticalMovementDistance() > m_MinDistanceForSwipe || HorizontalMovementDistance() > m_MinDistanceForSwipe;
    }

    private float VerticalMovementDistance() {
        return Mathf.Abs(m_FingerDownPosition.y - m_FingerUpPosition.y);
    }

    private float HorizontalMovementDistance() {
        return Mathf.Abs(m_FingerDownPosition.x - m_FingerUpPosition.x);
    }

    private void SendSwipe(SwipeDirection direction) {
        SwipeData swipeData = new SwipeData()
        {
            Direction = direction,
            StartPosition = m_FingerDownPosition,
            EndPosition = m_FingerUpPosition
        };
        OnSwipe(swipeData);
    }

0 个答案:

没有答案