检测触摸何时位于 UI 元素上

无限赢2

我正在创建一个触摸控制游戏,当您触摸和拖动时会旋转平台,但是我无法让它忽略跳跃按钮上的触摸,导致它认为您在一次长滑动时很快将同一根手指移到它上面. 我尝试跟踪起点和 ID,但是我意识到如果没有检测触摸是否在跳跃按钮上的方法,这些都不会起作用。

我用于检测触摸的代码:

int x = 0;
        while (x < Input.touchCount)
        {
            Touch touch = Input.GetTouch(x); // get the touch
            if (touch.phase == TouchPhase.Began) //check for the first touch
            {
                fp = touch.position;
                lp = touch.position;
            }
            else if (touch.phase == TouchPhase.Moved) // update the last position based on where they moved
            {
                lp = touch.position;
            }
            else if (touch.phase == TouchPhase.Ended) //check if the finger is removed from the screen
            {
                lp = touch.position;  //last touch position. Ommitted if you use list

            }
            if (!EventSystem.current.IsPointerOverGameObject(x))
            {
                int movement = ((int)(fp.x - lp.x));
                if (previous_fp != fp ^ x != previous_id)
                {
                    previous_rotate = 0;
                }
                previous_fp = fp;
                previous_id = x;
                if (!game_over) { Platform_Control.transform.Rotate(0f, 0f, -((movement - previous_rotate) * 0.15f), Space.World); }
                previous_rotate = movement;
            }
            x++;
        }
雨果

Afaik 这里的一个问题是您正在使用x触摸索引。IsPointerOverGameObject需要一个fingerID作为参数!

该指数x使用的触摸GetTouch必然等于Touch.fingerId

应该是

if(!EventSystem.current.IsPointerOverGameObject(touch.fingerId))

顺便说一句,总的来说,如果您要遍历所有触摸,则使用起来更容易 Input.touches

返回表示最后一帧期间所有触摸状态的对象列表。(只读)(分配临时变量)。

var touches = Input.touches;

它允许您立即过滤触摸,例如

using System.Linq;

...


var touches = Input.touches;
var validTouches = touches.Where(touch => !EventSystem.current.IsPointerOverGameObject(touch.fingerId));
foreach(var touch in validTouches)
{
    ...
}

这是使用LinqWhere并且基本上等于做

var touches = Input.touches;
foreach(var touch in touchs)
{
    if(!EventSystem.current.IsPointerOverGameObject(touch.fingerId)) continue;

    ...
}

一般来说,它仍然让我困惑如何/为什么应该使用相同的共享变量fp以及lp所有可能的接触。

您可能更应该使用

var moved = touch.deltaPosition;

而是使用该值。

或者通常通过存储第一个有效touch.fingerId然后检查触摸是否仍然是该 id 来仅使用这些触摸中的一个同时忽略所有其他触摸。

private int currentFingerId = int.MinValue;

...

// If you check that one first you can avoid a lot of unnecessary overhead ;)
if(!gameOver)
{   
    var touches = Input.touches;
    var validTouches = touches.Where(touch => !EventSystem.current.IsPointerOverGameObject(touch.fingerId);
    foreach (var touch in validTouches)
    {
        if(currentFingerId != int.MinValue && touch.fingerId != currentFingerId) continue;

        switch(touch.phase)
        {
            case TouchPhase.Began:
                currentFingerId = touch.fingerId;
                break;

            case TouchPhass.Moved:
                // "touch.deltaPosition.x" is basically exactly what you calculated
                // yourself using the "fp", "lp", "previous_rotate" and "movement"
                var moved = touch.deltaPosition.x * 0.15f;
                Platform_Control.transform.Rotate(0f, 0f, moved, Space.World);
                break;

            case TouchPhase.Ended:
                currentFingerId = int.MinValue;
                break;
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章