【问题标题】:Detect swipes without lifting the finger in Unity [duplicate]在Unity中无需抬起手指即可检测滑动[重复]
【发布时间】:2017-06-27 14:24:52
【问题描述】:

我正在实现特定类型的触摸控制器。 玩家需要将手指放在屏幕上才能移动。 在不抬起手指的情况下,玩家可以在移动的同时向不同方向滑动以改变方向。 一旦手指抬起,播放器就会停止移动。

很难隔离特定的滑动(即在屏幕上绘制的线条)而忽略任何其他不打算绘制线条的动作。 例如,当玩家的手指“静止”时,手指的轻微移动会破坏我的算法。

我考虑了不同的方法,例如存储最后几次触摸并评估它们以确定是否有滑动,但无法正确实施。

这是我迄今为止尝试过的。大多数情况下它运行良好,但玩家经常做不稳定的运动并且完全与我的预期相反。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchInputHandler : AbstractInputHandler {

    private const int SWIPE_MIN_DISTANCE = 35;

    private Vector2 touchStartPoint;

    private Vector2 touchMovePoint;

    void Update () {
        Touch[] touches = Input.touches;
        if (touches.Length == 1) {
            Touch firstTouch = touches [0];
            if (firstTouch.phase == TouchPhase.Began) {
                this.touchStartPoint = firstTouch.position;
                fireNextDirectionChanged (currentDirection);
            } else if (firstTouch.phase == TouchPhase.Moved) {
                this.touchMovePoint = firstTouch.position;
                if (Vector2.Distance(touchStartPoint, touchMovePoint) > SWIPE_MIN_DISTANCE) {
                    detectSwipeDirection ();
                }
            } else if (firstTouch.phase == TouchPhase.Stationary) {
                touchStartPoint.x = touchMovePoint.x;
                touchStartPoint.y = touchMovePoint.y;
            } else if (firstTouch.phase == TouchPhase.Ended) {
                fireNextDirectionChanged (Constants.Direction.NONE);
            }
        }
    }

    private void detectSwipeDirection() {
        float xDiff = touchMovePoint.x - touchStartPoint.x;
        float yDiff = touchMovePoint.y - touchStartPoint.y;
        Constants.Direction nextDirection;
        bool yGreater = Mathf.Abs(yDiff) >= Mathf.Abs(xDiff);
        if (yGreater) {
            // direction is up or down
            nextDirection = yDiff < 0 ? Constants.Direction.DOWN : Constants.Direction.UP;
        } else {
            // direction is left or right
            nextDirection = xDiff < 0 ? Constants.Direction.LEFT : Constants.Direction.RIGHT;
        }

        if (nextDirection != this.currentDirection)
        {
            fireNextDirectionChanged (nextDirection);
            this.currentDirection = nextDirection;
        }
    }
}

【问题讨论】:

  • @Programmer,这个问题怎么重复?你读过这个问题吗
  • 两个问题都说“检测滑动”。至于“不举手”,请检查答案。它具有设置为 false 的 detectSwipeOnlyAfterRelease 变量。请告诉我,什么不会使这个重复?
  • @Programmer 是的,你是对的,我在那里阅读了答案,根据我的需要对其进行了一些修改并解决了我的问题。我是发布我的解决方案并接受它还是将其作为重复项关闭?
  • 它已经关闭,但您可以提出自己的答案。还链接到您修改的原始代码。

标签: c# unity3d touch swipe


【解决方案1】:

我认为您只是忘记了将TouchPhase.Moved 块中的前一个触摸位置设置为当前位置的行。只需添加touchStartPoint = this.touchMovePoint;,它应该可以工作(仅使用鼠标输入进行测试,但逻辑保持不变)。

我还评论了TouchPhase.Stationary 块:我觉得它就像我之前建议的那样,但只有当手指完全不动时。最终代码如下所示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchInputHandler : AbstractInputHandler
{

    private const int SWIPE_MIN_DISTANCE = 35;

    private Vector2 touchStartPoint;

    private Vector2 touchMovePoint;

    void Update()
    {
        Touch[] touches = Input.touches;
        if(touches.Length == 1)
        {
            Touch firstTouch = touches[0];
            if(firstTouch.phase == TouchPhase.Began)
            {
                this.touchStartPoint = firstTouch.position;
                this.currentDirection = Constants.Direction.NONE;
                fireNextDirectionChanged(currentDirection);
            }
            else if(firstTouch.phase == TouchPhase.Moved)
            {
                this.touchMovePoint = firstTouch.position;
                if(Vector2.Distance(touchStartPoint, touchMovePoint) > SWIPE_MIN_DISTANCE)
                {
                    detectSwipeDirection();
                }
                touchStartPoint = this.touchMovePoint; // <= NEW !
            }
            //else if(firstTouch.phase == TouchPhase.Stationary)
            //{
            //    touchStartPoint.x = touchMovePoint.x;
            //    touchStartPoint.y = touchMovePoint.y;
            //}
            else if(firstTouch.phase == TouchPhase.Ended)
            {
                this.currentDirection = Constants.Direction.NONE;
                fireNextDirectionChanged(Constants.Direction.NONE);
            }
        }
    }

    private void detectSwipeDirection()
    {
        float xDiff = touchMovePoint.x - touchStartPoint.x;
        float yDiff = touchMovePoint.y - touchStartPoint.y;
        Constants.Direction nextDirection;
        bool yGreater = Mathf.Abs(yDiff) >= Mathf.Abs(xDiff);
        if(yGreater)
        {
            // direction is up or down
            nextDirection = yDiff < 0 ? Constants.Direction.DOWN : Constants.Direction.UP;
        }
        else
        {
            // direction is left or right
            nextDirection = xDiff < 0 ? Constants.Direction.LEFT : Constants.Direction.RIGHT;
        }

        if(nextDirection != this.currentDirection)
        {
            fireNextDirectionChanged(nextDirection);
            this.currentDirection = nextDirection;
        }
    }
}

此外,当使用基于游戏距离的距离来检测滑动时,如果您想将项目移植到多分辨率设备,我建议在某处添加Screen.width/height 比率(在Start() 上执行类似SWIPE_MIN_DISTANCE *= Screen.width / BASE_SCREEN_WIDTH 的操作private const int BASE_SCREEN_WIDTH = 1024;)。

希望对你有帮助,

【讨论】:

  • 嘿伙计,试过了,但很少让我的玩家能够移动,更不用说改变方向了。代码有问题。你测试了吗?
  • “它应该可以工作(仅使用鼠标输入进行测试,但逻辑保持不变)。”:当然我在发布之前对其进行了测试。唯一的区别是我使用了Input.GetMouseButton/Up/Down(0) 而不是firstTouch.phase == TouchPhase.Began/Moved/Ended
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多