检查触摸区域时触摸速度很慢

时间:2020-02-25 15:04:50

标签: c# android unity3d drag-and-drop

我有一个名为TouchDragDrop.cs的脚本,它可以让我在2D空间中触摸和拖动对象。

我要显示的两个功能是:

void Update()
{
    if (Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);
        // touchPosition = touch.position; 
        touchPosition = Camera.main.ScreenToWorldPoint(touch.position);

        switch (touch.phase)
        {
            case TouchPhase.Began: beginTouchMove();  break;
            case TouchPhase.Moved: moveTouch();  break;
            case TouchPhase.Stationary: stationaryTouch(); break;
            case TouchPhase.Ended: endTouchMove();  break;
        }

    }
}

private void moveTouch()
{
    //if ((myCollider2D == Physics2D.OverlapPoint(touchPosition)) && (isMoving))
    if(isMoving)
    {
        Vector2 newPosition = new Vector2(touchPosition.x - deltaX, touchPosition.y - deltaY);
        //gameObject.transform.position = newPosition;
        myRigidbody2D.MovePosition(newPosition);
        //if(debuglog) Debug.Log("Touch Position:  x: " + touchPosition.x.ToString() + " y: " + touchPosition.y.ToString());
        //if(debuglog) Debug.Log("RigidBody: " + myRigidbody2D.position.ToString());
    }
}

现在,要准确地移动对象,我需要确保触摸位于对象的顶部,这就是为什么我最初有这条线的原因:

if ((myCollider2D == Physics2D.OverlapPoint(touchPosition)) && (isMoving))

但是这会使应用程序减慢速度,以至于拖拽是艰苦的工作,就像我真的必须缓慢地拖拽以使角色与我一起移动一样。因此,如果我将其取出来,只是再次if(isMoving)就快了。

如何确保仅拖动对象而不只是拖动屏幕的一部分?

1 个答案:

答案 0 :(得分:1)

我只能假定您有许多运行此脚本的对象,这就是导致您出现问题的原因。要验证这一点,请尝试将具有 TouchDragDrop 组件的对象的数量减少到1或2个。您可能会注意到游戏不再缓慢。

每次触摸屏幕时,所有带有 TouchDragDrop.cs 脚本的对象都会读取输入,然后执行其moveTouch逻辑。如果您有50个附加了 TouchDragDrop.cs 的对象,则将执行Physics2D.OverlapPoint 50次。这可能会损害您的表现。

Physics2D.OverlapPoint只能调用一次。如果许多对象需要响应您的触摸,请考虑将“输入”和“触摸”逻辑移动到仅负责读取输入并返回击中哪个对撞机的单个gameObject。然后将“运动逻辑”移动到其他脚本(也许称为 Draggable.cs ),而不是对每个GameObject进行比较,您都可以在单个输入脚本中执行以下操作:

touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
Collider2D touchedCollider = Physics2D.OverlapPoint(touchPosition)
Draggable dragObj = touchedCollider?.GetComponent<Draggable>();
dragObj?.MoveTouch(touchPosition);

更新

由于该问题目前与GameObjects的数量无关,因此很可能是由于Fixed周期与Frame周期之间的争用。我写了相当长的explanation of the differences between the 2,但总之我相信这可能是您的问题:

在移动时每一帧读取输入时,物理对象的碰撞器位置不会立即更新。它仅在“固定”周期更新,这意味着您的输入有少许机会移到对撞机之外。

这是一个新的解决方案:

让我们假设您只需要检查一次触摸位置(在TouchPhase.Began期间),而不是验证每帧都在触摸对象。我推荐这样的东西:

void BeginTouchMove()
{
    if(myCollider2D == Physics2D.OverlapPoint(touchPosition))
    {
        isMoving = true;
    }
}

然后,只需检查(isMoving),即可使MoveTouch()逻辑与上面相同。