根据代码的逻辑,在触摸屏幕时,首先会判断是否触摸到了角色。这里使用了 Physics2D.OverlapPoint
方法来检测碰撞物体,但是传入的坐标是使用 ScreenToWorldPoint
方法转换得到的。
可能出现问题的原因是,转换得到的世界坐标和实际碰撞检测所需的世界坐标有一定偏差或误差,导致检测不准确。可以尝试将判断选中角色的条件改为更加精确的方式,例如使用 Collider2D.OverlapPoint
方法进行碰撞检测,并将触摸点位置转换为局部坐标系下的位置再进行判断。
具体修改方法如下:
- 将
Update()
中对触摸事件的处理改为:
if (Input.touchCount > 0) // 检测是否有触摸事件发生
{
Touch touch = Input.GetTouch(0); // 获取第一个触点的信息
switch (touch.phase)
{
case TouchPhase.Began:
if (!IsTouchedOnPlayer(touch.position)) // 如果没有触摸到角色,则在角色脚下生成光圈,并返回,不进行移动操作
currentCircle = Instantiate(circlePrefab, transform.position, Quaternion.identity);
break;
case TouchPhase.Moved:
if (currentCircle != null) // 如果有光圈,则在手指移动的位置生成另外一个光圈(不移动角色)
{
Vector3 touchPos = Camera.main.ScreenToWorldPoint(touch.position); // 将屏幕坐标转换为世界坐标
touchPos.z = 0;
currentCircle.transform.position = touchPos;
}
break;
case TouchPhase.Ended:
case TouchPhase.Canceled:
if (currentCircle != null)
Destroy(currentCircle);
if (IsTouchedOnPlayer(touch.position)) // 如果结束时还在角色身上,则直接返回,不进行移动操作
return;
Vector2 targetPos = Camera.main.ScreenToWorldPoint(touch.position);
targetPosition = targetPos; // 将屏幕坐标转换为世界坐标,作为目标位置
if (currentCoroutine != null)
StopCoroutine(currentCoroutine);
currentCoroutine = StartCoroutine(MoveToTarget());
break;
}
}
- 添加新的方法
IsTouchedOnPlayer
用于判断是否触摸到了角色:
private bool IsTouchedOnPlayer(Vector2 screenPosition)
{
Vector2 worldPosition = Camera.main.ScreenToWorldPoint(screenPosition);
Collider2D[] colliders = GetComponents<Collider2D>();
foreach (var collider in colliders)
{
if (collider.OverlapPoint(worldPosition))
{
return true;
}
}
return false;
}
通过以上修改,应该可以解决触摸任意位置都会被判断为选中角色的问题。