You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D角色沿圆周移动碰撞失效问题求助

解决2D角色圆周移动碰撞穿透/抖动问题

问题根源:rb.MovePosition()是直接强制将刚体瞬移到目标位置,物理引擎无法对这种瞬时位移做出正确的碰撞响应,导致碰到墙体时出现抖动甚至穿墙。

下面是两种可行的解决方案:

方案1:用速度驱动圆周运动(推荐)

让物理引擎通过速度控制角色移动,自然处理碰撞逻辑,这是最符合Unity物理系统的做法:

private void FixedUpdate()
{
    // 计算角色到圆心的方向向量
    Vector2 toCenter = _startPosition - (Vector2)_rb.position;
    
    // 确保角色始终保持在设定的圆周半径上(碰撞后可能偏离,需要修正)
    if (Mathf.Abs(toCenter.magnitude - _radius) > 0.01f)
    {
        _rb.position = _startPosition + toCenter.normalized * _radius;
    }

    // 计算圆周运动的切线方向(垂直于圆心方向)
    Vector2 tangentDir = new Vector2(-toCenter.y, toCenter.x).normalized;

    // 根据输入设置切线方向的速度
    if (Input.GetKey(KeyCode.A))
    {
        _rb.velocity = tangentDir * _speed;
    }
    else if (Input.GetKey(KeyCode.D))
    {
        _rb.velocity = -tangentDir * _speed;
    }
    else
    {
        _rb.velocity = Vector2.zero;
    }
}

同时调整刚体设置:

  • 刚体类型设为Dynamic(必须,让刚体受物理规则约束)
  • 关闭刚体的Gravity Scale(如果不需要重力)
  • 墙体只需要添加Collider2D并设置为Static(不需要给墙体加刚体,Static碰撞体即可触发碰撞)

方案2:保留角度控制,添加碰撞检测修正

如果坚持用角度计算位置,需要在移动前检测路径上的障碍物,避免强制穿墙:

private void FixedUpdate()
{
    var targetPosition = _startPosition + new Vector2(Mathf.Cos(_angle * Mathf.Deg2Rad), Mathf.Sin(_angle * Mathf.Deg2Rad)) * _radius;
    Vector2 moveVector = targetPosition - (Vector2)_rb.position;

    // 检测移动路径是否被墙体阻挡(替换"Wall"为你的墙体图层名)
    RaycastHit2D hit = Physics2D.Raycast(_rb.position, moveVector.normalized, moveVector.magnitude, LayerMask.GetMask("Wall"));
    if (hit.collider != null)
    {
        // 碰到墙,回退到上一帧的角度,不执行移动
        _angle = _oldAngle;
        return;
    }

    _rb.MovePosition(targetPosition);
}

这种方法需要手动处理碰撞后的回退逻辑,体验不如速度驱动流畅,但可以保留你原本的角度控制逻辑。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:32:03