繁体   English   中英

Unity3d 如何检测 android 上的点击?

[英]Unity3d How to detect taps on android?

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

我将水龙头定义为

  • 手指最初接触手机和最终退出手机之间的时间很短

  • 很少或没有运动

感谢您阅读本文,我希望它清晰准确,如果需要代表我的任何细节或帮助以便您回答,请随时提问。 任何帮助表示感谢。 谢谢。

注意 - 我在 C# 中工作

首先,您必须确定您的 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。 祝你好运! :)

做了一些搜索(谷歌搜索“unity mobile detection tap”)后,我发现这是最热门的搜索结果。 @Mothil 的回答让我们非常接近解决方案,而 OP 的回答解决了这个问题。 但是,OP 的答案并未考虑多次点击。 也不需要跟踪开始的触摸、结束的触摸和移动的触摸(例如int SCount, MCount, ECount )的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 进入和离开时没有检测到任何移动。 检测到每个手指的轻敲,并将每个轻敲的位置打印到控制台。

在此处输入图片说明

我很确定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)
                    {
                    }
                }

i 是因为我想知道用户有多少触摸,但这至少应该让你继续前进。

编辑:我忘了提到,您可能需要在协程中使用 if 语句块。

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

希望这会有所帮助。

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

很少或没有运动

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

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

这是我的代码 -

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

简单而有效,只需在顶部 UI 中添加引擎并在更新沙丘中添加代码

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM