我有一个名为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)
就快了。
如何确保仅拖动对象而不只是拖动屏幕的一部分?
答案 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()逻辑与上面相同。