Unity3d如何检测android上的点击?

时间:2016-08-02 19:13:27

标签: c# unity3d touch

目前我正在努力研究如何创建一个简单的代码,告诉我是否发生了一个点击,让我获得了点击的位置。浏览了很多不同的文章后,我很反感Touch.tapCount经常被认为只适用于ios。另外,我尝试使用Touch.deltaTime和/或Touch.deltaPosition来检测点击但是失败了。

我将自来水定义为

  • 手指最初触摸并最终退出手机之间的时间非常短

  • 很少或没有动作

感谢您阅读此内容,我希望我的内容清晰准确,如果有任何细节或帮助,请您随时回答。感谢任何协助。感谢。

注意 - 我在C#中工作

5 个答案:

答案 0 :(得分:4)

首先,您必须了解您的Android设备是否确实可以注册多个触摸。如果您有更新的设备,这应该不是问题。我会假设您的设备可以,如果不能 - 您很快就会发现它。

让我们从更新方法开始。

void Update() {
// Nothing at the moment
}

我们首先要做的是注册接触。我们可以通过将foreach置于内部,检查Input.touches中的触摸来完成此操作。像这样:

    void Update() {
    foreach (Touch touch in Input.touches) {

    }
}

通过这样做,我们总是检查屏幕上当前有多少触摸。我们现在可以做的是通过fingerId检查,如果fingerId == 0,1,2 ......运行一些代码。这是我们现在得到的:

    void Update() {
        foreach (Touch touch in Input.touches) {

        if (touch.fingerId == 0) {
            // Finger 1 is touching! (remember, we count from 0)
        }

        if (touch.fingerId == 1) {
            // finger 2 is touching! Huzzah!
        }
    }
}

到目前为止我们很棒!我们现在想做的是检测我们想要的动作。在我们的例子中,我们想要点击,对吗?这应该与TouchPhase Began和Ended完美配合。还有TouchPhase.Moved,但我们现在不需要它。

if (touch.fingerId == 0) {

    if (Input.GetTouch(0).phase == TouchPhase.Began) {
        Debug.Log("First finger entered!");
    }

    if (Input.GetTouch(0).phase == TouchPhase.Ended) {
        Debug.Log("First finger left.");
    }
}

这里我们正在检查相应手指的相位。如果您现在运行,您应该能够在第一次触摸进入时在控制台中看到消息,并离开屏幕。这可以通过几次触摸完成,所以这里是'整个'脚本:

    void Update() {
    foreach (Touch touch in Input.touches) {

        if (touch.fingerId == 0) {
            if (Input.GetTouch(0).phase == TouchPhase.Began) {
                Debug.Log("First finger entered!");
            }
            if (Input.GetTouch(0).phase == TouchPhase.Ended) {
                Debug.Log("First finger left.");
            }
        }

        if (touch.fingerId == 1) {
            if (Input.GetTouch(1).phase == TouchPhase.Began) {
                Debug.Log("Second finger entered!");
            }
            if (Input.GetTouch(1).phase == TouchPhase.Ended) {
                Debug.Log("Second finger left.");
            }
        }
    }
}

我希望这会对你有所帮助。我自己也很陌生,所以如果我们很幸运,有经验的人可以来帮忙。我相信这可以写得更清洁。请记住,如果您构建它,则无法看到控制台消息。如果您还没有,请查看Unity Remote。祝好运! :)

答案 1 :(得分:0)

我很确定tapCount可以在Android上运行。 在我的场景中,处理输入的内容不是从MonoBehaviour派生的。相反,它只是我传递的对象。我不会提供完整的课程,但只能处理电话触摸/点击。

if (Input.touchCount > i)
                {
                    if (Input.GetTouch(i).phase == TouchPhase.Began)
                    {
                    }
                    if (Input.GetTouch(i).phase == TouchPhase.Canceled)
                    {
                    }
                    if (Input.GetTouch(i).phase == TouchPhase.Ended)
                    {
                    }
                    if (Input.GetTouch(i).phase == TouchPhase.Moved)
                    {
                    }
                    if (Input.GetTouch(i).phase == TouchPhase.Stationary)
                    {
                    }
                }

我是因为我想知道用户有多少触摸,但这应该让你至少去。

编辑:我忘了提一下,你可能想要一个coroutine中的if语句块。

https://docs.unity3d.com/Manual/Coroutines.html

希望这有帮助。

答案 2 :(得分:0)

感谢大家的回复,我很感激,我确信有几种不同的方法来检测水龙头。下面是我的代码,它已被提示有关阶段,使用阶段来判断触摸是否有运动阶段或不允许我判断触摸是否已移动,实现以下的分接特性:

  

很少或没有动作

此外,通过查看触摸开始和结束阶段之间经过的时间,我可以检测到敲击的第二个特征,即:

  

手指最初接触和最后之间的间隔很短   退出电话

以下是我的代码 -

using UnityEngine;
using System.Collections;

public class TouchManager : MonoBehaviour
{
    public Vector2 touchPos;
    int SCount; // Count of started touches
    int MCount; // Count of ended touches
    int ECount; // Count of moved touches
    int LastPhaseHappend; // 1 = S, 2 = M, 3 = E
    float TouchTime; // Time elapsed between touch beginning and ending
    float StartTouchTime; // Time.realtimeSinceStartup at start of touch
    float EndTouchTime; // Time.realtimeSinceStartup at end of touch

    void Start()
    {
        SCount = 0;
        MCount = 0;
        ECount = 0;
        StartTouchTime = 0;
        EndTouchTime = 0;
        TouchTime = 0;
        // All variables are intialized at zero, likely uneccessary as i believe they're 'zeroed' by default
    }

    // Update is called once per frame
    void Update()
    {
        touchPos = Vector3.zero;
        if (Input.touchCount != 0)
        {
            Touch currentTouch = Input.GetTouch(0);
            switch (currentTouch.phase)
            {
                case TouchPhase.Began:
                    if (LastPhaseHappend != 1)
                    {
                        SCount++;
                        StartTouchTime = Time.realtimeSinceStartup;
                    }
                    LastPhaseHappend = 1;
                    break;

                case TouchPhase.Moved:
                    if (LastPhaseHappend != 2)
                    {
                        MCount++;
                    }
                    LastPhaseHappend = 2;
                    break;

                case TouchPhase.Ended:
                    if (LastPhaseHappend != 3)
                    {
                        ECount++;
                        EndTouchTime = Time.realtimeSinceStartup;
                        TouchTime = EndTouchTime - StartTouchTime;
                    }
                    LastPhaseHappend = 3;
                    break;
            }
            if (SCount == ECount && ECount != MCount && TouchTime < 1)
                // TouchTime for a tap can be further defined
            {
                //Tap has happened;
                touchPos = currentTouch.position;
                MCount++;
            }
        }
    }
}

答案 3 :(得分:0)

进行了一些搜索(使用Google搜索“ unity mobile detect tap”)后,我发现它是搜索结果的顶部。 @Mothil的答案使我们非常接近解决方案,OP的答案解决了问题。但是,OP的答案不能说明多次点击。此外,也不必跟踪开始触摸,结束触摸和移动触摸(例如int SCount, MCount, ECount)的计数。

相反,我们可以像@mothil一样直接遍历每个触摸并通过其fingerId跟踪每个单独的触摸。为此,我们将需要两个阵列来跟踪抽头的特性:1)短延时,以及2)无移动。在下面的数组中,数组索引为fingerId。

private float[] timeTouchBegan;
private bool[] touchDidMove;

我们还需要一个变量来存储所需的抽头时间阈值。在测试中,我发现阈值0.2f效果很好。

private float tapTimeThreshold = 0.2f;

Start()函数中,我们将对其进行初始化,以容纳10个元素进行10次触摸。可以将其修改为任何需要的触摸。

Update()函数中,我们通过每次触摸来循环。如果在TouchPhase.Began中,则将timeTouchBegan[fingerIndex]设置为当前时间;我们还将touchDidMove[fingerIndex]设置为false。

如果在TouchPhase.Moved中,我们将touchDidMove[fingerIndex]设置为true。

最后,在TouchPhase.Ended中,我们可以计算点击时间。

float tapTime = Time.time - timeTouchBegan[fingerIndex];

如果点击时间少于阈值并且触摸没有移动,则我们有经过验证的点击。

if (tapTime <= tapTimeThreshold && touchDidMove[fingerIndex] == false)
{
    // Tap detected at touch.position
}

完整脚本

这是完整的课程:

public class TapManager : MonoBehaviour
{        
    private float[] timeTouchBegan;
    private bool[] touchDidMove;
    private float tapTimeThreshold = 0.2f;

    void Start()
    {
        timeTouchBegan = new float[10];
        touchDidMove = new bool[10];
    }

    private void Update()
    {
        // Touches
        foreach (Touch touch in Input.touches)
        {
            int fingerIndex = touch.fingerId;

            if (touch.phase == TouchPhase.Began)
            {
                Debug.Log("Finger #" + fingerIndex.ToString() + " entered!");
                timeTouchBegan[fingerIndex] = Time.time;
                touchDidMove[fingerIndex] = false;
            }
            if (touch.phase == TouchPhase.Moved)
            {
                Debug.Log("Finger #" + fingerIndex.ToString() + " moved!");
                touchDidMove[fingerIndex] = true;
            }
            if (touch.phase == TouchPhase.Ended)
            {
                float tapTime = Time.time - timeTouchBegan[fingerIndex];
                Debug.Log("Finger #" + fingerIndex.ToString() + " left. Tap time: " + tapTime.ToString());
                if (tapTime <= tapTimeThreshold && touchDidMove[fingerIndex] == false)
                {
                    Debug.Log("Finger #" + fingerIndex.ToString() + " TAP DETECTED at: " + touch.position.ToString());
                }
            }            
        }
    }   
}

统一测试

我使用Unity Remote在游戏中对此进行了测试。在下面的屏幕截图中,您可以看到我的调试控制台日志。我做了四个手指的点击。您会看到手指0到3进入并离开,没有检测到任何移动。检测到每个手指都有一个轻拍,并且每个轻拍的位置都被打印到控制台上。

enter image description here

答案 4 :(得分:0)

简单但有效,jsut在顶部UI处添加引擎,并在更新沙丘中添加代码

enter image description here