Unity3d如何在安卓设备上检测点击?

11

我目前正在努力想出如何创建一个简单的代码,来判断是否发生了轻触,并获取轻触位置。经过查阅许多不同的文章,我对于经常被建议使用的Touch.tapCount感到有些困惑,因为它只适用于iOS设备。此外,我尝试使用Touch.deltaTime和/或Touch.deltaPosition来检测轻触,但是没有成功。

我将轻触定义为:

  • 手指最初接触和最终离开手机之间非常短暂的时间

  • 很少或没有移动

感谢阅读,希望我的问题清晰明确,如果需要我提供任何详细信息或帮助以便您回答,请随时询问。非常感谢任何帮助。注意 - 我使用C#。


只需使用UI.Button即可。 - Fattie
@JoeBlow UI.Button 如何对“手指最初触摸和最终离开手机之间的非常短时间”进行选择? - g_l
UI.Button存在的目的是确定手指最初接触和最终退出手机之间是否有非常短的时间段。 - Fattie
纯粹提供信息,如果你要接触Unity,这可能会帮助很多 https://dev59.com/oloU5IYBdhLWcg3wamga#37473953 - Fattie
4个回答

14

首先,您需要确定您的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,请查看一下。祝你好运! :)


2

在进行一些搜索后(谷歌搜索“unity mobile detect tap”),我发现这是最顶部的搜索结果。@Mothil的回答让我们非常接近解决方案,OP的回答解决了问题。但是,OP的答案没有考虑多次点击。此外,跟踪已启动触摸、已结束触摸和已移动触摸(例如int SCount,MCount,ECount)的数量并不是必要的。

相反,我们可以直接通过每个触摸循环,并通过其fingerId跟踪每个单独的触摸,就像@mothil所做的那样。为此,我们需要两个数组来跟踪点击的特征: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测试

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

enter image description here


0

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

输入图像描述


我无法做到,这是不可能的。 - Aras Tahiron

-1

我非常确定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

希望这能有所帮助。

说实话,我并不太理解你的代码,但我想通过使用阶段可能会有所帮助,因为我可以检查触摸是否已经经历了开始和结束阶段而没有移动阶段,从而实现轻拍。我将测试一下。如果您有任何进一步的代码解释,欢迎分享。@MrKeeame - g_l
此外,它在Android上无法工作,因此“Android设备不会计算点击次数,该字段始终为1。”直接来自Unity手册http://docs.unity3d.com/Manual/MobileInput.html - g_l
可能是Unity版本的差异,但我在iOS和Android上的几个游戏中都有这段代码。话虽如此,一旦我回家,我会更新我的答案,希望能更好地帮助你。@g_l - TheNoob
在tapCount和touchCount之间可能有区别吗?不管怎样,我稍后会为您更新。 - TheNoob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接