在Unity中

时间:2017-06-27 14:24:53

标签: c# unity3d touch swipe unityscript

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

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

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

这是我到目前为止所尝试的内容。大部分时间它运作良好,但通常玩家运动不稳定,并且与我的预期完全相反。

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;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我想你只是忘了一行将前一个触摸位置设置为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;之类的操作。

希望这有帮助,