【问题标题】:Unity3d How to detect taps on android?Unity3d如何检测android上的点击?
【发布时间】:2020-03-16 11:35:27
【问题描述】:

目前我正在努力研究如何创建一个简单的代码,它会告诉我是否发生了点击,让我能够获得点击的位置。浏览了许多不同的文章后,我很困惑Touch.tapCount,通常建议它只适用于 ios。另外,我尝试使用Touch.deltaTime 和/或Touch.deltaPosition 来检测水龙头但失败了。

我将点击定义为具有

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

  • 很少或没有运动

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

注意 - 我使用 C# 工作

【问题讨论】:

  • 只使用一个 UI.Button
  • @JoeBlow UI.Button 如何选择“手指最初触摸到最终退出手机之间的很短时间”?
  • UI.Button 用于确定手指最初触摸到最终退出手机之间是否有很短的时间。
  • 仅供参考,如果您正在接触 Unity,这可能会有很大帮助 stackoverflow.com/a/37473953/294884

标签: c# unity3d touch


【解决方案1】:

首先,您必须确定您的 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】:

    在进行了一些搜索(谷歌搜索“统一移动检测点击”)后,我发现这是最热门的搜索结果。 @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 进入和离开时没有检测到任何移动。检测到每个手指的轻敲,并将每个轻敲的位置打印到控制台。

    【讨论】:

      【解决方案3】:

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

      enter image description here

      【讨论】:

      • 我不可能的
      【解决方案4】:

      我很确定 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
      • 另外,它不适用于 Android,因此“Android 设备不计算点击次数,此字段始终为 1。”直接来自统一手册docs.unity3d.com/Manual/MobileInput.html
      • 嗯,可能是统一版本的差异,但我在 ios 和 android 上的几款游戏中都获得了该代码。但是,话虽如此,一旦我回家,我会更新我的答案,希望能帮助你更多。 @g_l
      • tapCount 和 touchCount 有区别吗?无论如何,稍后我会为您提供更新。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      相关资源
      最近更新 更多