【问题标题】:swipe gestures on android in unity统一在android上滑动手势
【发布时间】:2014-12-30 20:39:30
【问题描述】:

我正在努力让统一认识到我正在从左向右滑动,我已经解决了这个问题,但我的问题是,直到我将手指从屏幕上移开,它才理解这一点。

我的问题是如何让它知道我向右走,然后又向左走,然后又向右走,而我的手指从来没有用过屏幕

这是我目前的代码

using UnityEngine;
using System.Collections;

public class Gestures : MonoBehaviour {

private Vector2 fingerStart;
private Vector2 fingerEnd;

public int leftRight = 0;
public int upDown = 0;

void Update () {
    foreach(Touch touch in Input.touches)
    {
        if (touch.phase == TouchPhase.Began)
        {
            fingerStart = touch.position;
            fingerEnd  = touch.position;
        }
        if (touch.phase == TouchPhase.Moved )
        {
            fingerEnd = touch.position;

        }
        if(touch.phase == TouchPhase.Ended)
        {
            if((fingerStart.x - fingerEnd.x) > 80 || (fingerStart.x - fingerEnd.x) < -80) // Side to side Swipe
            {
                leftRight ++;
            }
            else if((fingerStart.y - fingerEnd.y) < -80 || (fingerStart.y - fingerEnd.y) > 80) // top to bottom swipe
            {
                upDown ++;

            }
            if(leftRight >= 3){

                leftRight = 0;
            }
            if(upDown >= 4){

                upDown = 0;
            }
        }
    }
}
}

【问题讨论】:

    标签: android input unity3d touch gestures


    【解决方案1】:

    您面临的问题是因为您已在 TouchPhase.Ended 中完成检查。您要做的是在 TouchPhase.Moved 中执行检查,值的变化较小(您在 Ended 中使用 80,如果代码不起作用,请尝试 10 之类的值)

    Unity 关于 TouchPhase 的文档http://docs.unity3d.com/ScriptReference/TouchPhase.html

        foreach(Touch touch in Input.touches)
        {
    
            if (touch.phase == TouchPhase.Began)
            {
                fingerStart = touch.position;
                fingerEnd  = touch.position;
            }
            if (touch.phase == TouchPhase.Moved )
            {
                fingerEnd = touch.position;
    
                if((fingerStart.x - fingerEnd.x) > 80 || 
                   (fingerStart.x - fingerEnd.x) < -80) // Side to side Swipe
                {
                    leftRight ++;
                }
                else if((fingerStart.y - fingerEnd.y) < -80 || 
                        (fingerStart.y - fingerEnd.y) > 80) // top to bottom swipe
                {
                    upDown ++;
    
                }
                if(leftRight >= 3){
    
                    leftRight = 0;
                }
                if(upDown >= 4){
    
                    upDown = 0;
                }
    
                //After the checks are performed, set the fingerStart & fingerEnd to be the same
                fingerStart = touch.position;   
    
            }
            if(touch.phase == TouchPhase.Ended)
            {
                leftRight = 0;
                upDown = 0;
                fingerStart = Vector2.zero;
                fingerEnd = Vector2.zero;
            }
    




    如果您想明确检查模式(即左 -> 右 -> 左),而不是像您拥有的代码那样检查它是否是某种横向/垂直移动,请尝试以下代码。只要记住包含 System.Collentions.Generic 和 System.Linq 命名空间

    private Vector2 fingerStart;
    private Vector2 fingerEnd;
    
    public enum Movement
    {
        Left,
        Right, 
        Up,
        Down
    };
    
    public List<Movement> movements = new List<Movement>();
    
    
    void Update () {
        foreach(Touch touch in Input.touches)
        {
    
            if (touch.phase == TouchPhase.Began) {
                fingerStart = touch.position;
                fingerEnd  = touch.position;
            }
    
            if(touch.phase == TouchPhase.Moved) {
                fingerEnd = touch.position;
    
                //There is more movement on the X axis than the Y axis
                if(Mathf.Abs(fingerStart.x - fingerEnd.x) > Mathf.Abs(fingerStart.y - fingerEnd.y)) {
    
                    //Right Swipe
                    if((fingerEnd.x - fingerStart.x) > 0)
                        movements.Add(Movement.Right);
                    //Left Swipe
                    else
                        movements.Add(Movement.Left);
    
                }
    
                //More movement along the Y axis than the X axis
                else {
                    //Upward Swipe
                    if((fingerEnd.y - fingerStart.y) > 0)
                        movements.Add(Movement.Up);
                    //Downward Swipe
                    else
                        movements.Add(Movement.Down);
                }
                //After the checks are performed, set the fingerStart & fingerEnd to be the same
                fingerStart = touch.position;   
    
                //Now let's check if the Movement pattern is what we want
                //In this example, I'm checking whether the pattern is Left, then Right, then Left again
                Debug.Log (CheckForPatternMove(0, 3, new List<Movement>() { Movement.Left, Movement.Right, Movement.Left } ));
            }
    
    
            if(touch.phase == TouchPhase.Ended)
            {
                fingerStart = Vector2.zero;
                fingerEnd = Vector2.zero;
                movements.Clear();
            }
        }
    }
    
    
    private bool CheckForPatternMove (int startIndex, int lengthOfPattern, List<Movement> movementToCheck) {
    
        //If the currently stored movements are fewer than the length of the pattern to be detected
        //it can never match the pattern. So, let's get out
        if(lengthOfPattern > movements.Count)
            return false;
    
        //In case the start index for the check plus the length of the pattern
        //exceeds the movement list's count, it'll throw an exception, so lets get out
        if(startIndex + lengthOfPattern > movements.Count)
            return false;
    
        //Populate a temporary list with the respective elements
        //from the movement list
        List<Movement> tMovements = new List<Movement>();
        for(int i = startIndex; i < startIndex + lengthOfPattern; i++)
            tMovements.Add(movements[i]);
    
        //Now check whether the sequence of movements is the same as the pattern you want to check for
        //The SequenceEqual method is in the System.Linq namespace
        return tMovements.SequenceEqual(movementToCheck);
    }
    



    编辑添加了更多代码作为示例

        //The idea of a pattern match is to check for the exact same set of swipe gesture.
        //This requires the following conditions to be met
        // (a) The List of movements that need to be checked must be at least as long as the List of movements to check against.
        // (b) The correct indices should be used for the startIndex. In this case I'm just using 0 as the startIndex.
        // (c) Remember to clear the List right after you get a true return from the method, otherwise the next return will most likely be a false. 
    
        //Example - Training set is Left -> Right -> Left (This is what we want to check)
        // Step 1 - User swipes LEFT, method returns false because there are too few Movements to check
        // Step 2 - User swipes RIGHT, method returns false (same reason as above)
    
        // Step 3a - User swipes RIGHT (L, R, R now) - false, incorrect pattern (L, R, R instead of L, R, L)
        // Step 3b - User swipes LEFT (L, R, L now) - TRUE, Correct pattern!
    
        //Immediately clear if Step 3b happens otherwise Step 4 will occur
    
        // Step 4 - User swipes L or R (direction is immaterial right now), and method will return FALSE
        // if you use the last three indexes!
    
    
    
        //Pre-populating the movements List with L, R, L
        movements = new List<Movement>()
        {
            Movement.Left,
            Movement.Right,
            Movement.Left
        };
    
        //Checking a match against an L, R, L training set
        //This prints true to the console
        Debug.Log (CheckForPatternMove(0, 3, new List<Movement>() { Movement.Left, Movement.Right, Movement.Left }  ));
    



    这是我的更新功能的样子。注意 GetMouseButton 在 Input.touch 上的使用

    void Update () {
    
        //Example usage in Update. Note how I use Input.GetMouseButton instead of Input.touch
    
        //GetMouseButtonDown(0) instead of TouchPhase.Began
        if (Input.GetMouseButtonDown(0)) {
            fingerStart = Input.mousePosition;
            fingerEnd  = Input.mousePosition;
        }
    
        //GetMouseButton instead of TouchPhase.Moved
        //This returns true if the LMB is held down in standalone OR
        //there is a single finger touch on a mobile device
        if(Input.GetMouseButton(0)) {
            fingerEnd = Input.mousePosition;
    
            //There was some movement! The tolerance variable is to detect some useful movement
            //i.e. an actual swipe rather than some jitter. This is the same as the value of 80
            //you used in your original code.
            if(Mathf.Abs(fingerEnd.x - fingerStart.x) > tolerance || 
               Mathf.Abs(fingerEnd.y - fingerStart.y) > tolerance) {
    
                //There is more movement on the X axis than the Y axis
                if(Mathf.Abs(fingerStart.x - fingerEnd.x) > Mathf.Abs(fingerStart.y - fingerEnd.y)) {
                    //Right Swipe
                    if((fingerEnd.x - fingerStart.x) > 0)
                        movements.Add(Movement.Right);
                    //Left Swipe
                    else
                        movements.Add(Movement.Left);
                }
    
                //More movement along the Y axis than the X axis
                else {
                    //Upward Swipe
                    if((fingerEnd.y - fingerStart.y) > 0)
                        movements.Add(Movement.Up);
                    //Downward Swipe
                    else
                        movements.Add(Movement.Down);
                }
    
                //After the checks are performed, set the fingerStart & fingerEnd to be the same
                fingerStart = fingerEnd;
    
                //Now let's check if the Movement pattern is what we want
                //In this example, I'm checking whether the pattern is Left, then Right, then Left again
                Debug.Log (CheckForPatternMove(0, 3, new List<Movement>() { Movement.Left, Movement.Right, Movement.Left } ));
            }
        }
    
        //GetMouseButtonUp(0) instead of TouchPhase.Ended
        if(Input.GetMouseButtonUp(0)) {
            fingerStart = Vector2.zero;
            fingerEnd = Vector2.zero;
            movements.Clear();
        }
    
    
    }
    

    【讨论】:

    • 如果答案对你有帮助,请标记为正确答案:)
    • 快速问题,我正在尝试您发布的第二个代码,但统一在 CheckForPatternMove() 中的前两个返回中抛出错误,说“需要一个可转换为 `bool' 类型的对象return 语句”我尝试将两者都设置为 false 和 true,但是当我尝试测试它是否检测到 (LRL) 模式时它总是返回 false 我只是将第二个代码复制粘贴到一个新脚本中并添加了上面提到的命名空间我做错了什么
    • 啊,第一个是我的错误。您需要在前两次检查中返回 false (这是因为模式无法匹配)。对于您的第二个问题,您很有可能使用了不正确的索引。我在上面编辑了我的帖子,详细说明了它是如何使用的。希望这能帮助你弄清楚。
    • 编辑时间用完了。啊,第一个是我的错误。您需要在前两次检查中返回 false 对于您的第二个问题,它可能是(a)用于检查的索引不正确,(b)由于容差低而添加了一些额外的点(c)输入。 touch 每次都会返回相当多的点,这会添加所有点。我在上面编辑了我的帖子,详细说明了我如何使用该方法。希望这会有所帮助。请注意,我通常使用 Input.GetMouseButton 而不是 Input.Touch。鼠标输入适用于移动设备并返回一个点。
    • 很高兴为您提供帮助
    猜你喜欢
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    相关资源
    最近更新 更多