unity Physics2D.Raycast 打自己

Unity Physics2D.Raycast hits itself

我正在尝试使用 Physics2D.Raycast 来检查玩家是否在地面上(我知道还有其他方法可以检查玩家是否在地面上,但我认为光线投射最靠谱)。 问题是在我的场景中 returns 玩家本身被击中了,我真的不明白为什么以及我应该做什么。 我的代码(在 PlayerController 中)如下:

 public bool IsGrounded () {
        Bounds bounds = this.playerCollider.bounds;
        Vector3 rayOrigin = bounds.center;
        rayOrigin.y -= bounds.extents.y;
        RaycastHit2D hit = Physics2D.Raycast (rayOrigin, Vector2.down, 0.1f);
        if (hit.collider != null) {
            Debug.Log ("Collider is: " + hit.collider.name);
        }
        return hit.collider != null;
    }

我可以使用以下方法调试投射光线:

Debug.DrawLine (rayOrigin, new Vector3 (rayOrigin.x, rayOrigin.y - 0.1f, rayOrigin.z), Color.magenta);

...它按预期进行了转换,而 Debug.Log 总是报告 "Player" 本身,我不知道这怎么可能。那怎么了?

ps。我正在使用 Unity 5.3

Vector2.down 向量并不总是呈现对象 space 的下向量。您可以使用 -transform.up

此外,如果可以接受,您可以在光线的起点添加一些填充,例如 rayOrigin.y += 0.0001f;

出现此问题是因为您的播放器在光线投射开始时重叠。有几种方法可以解决此问题:

1.禁用查询在碰撞器中启动.

转到编辑->项目设置->Physics 2D 然后确保Queries Start In Colliders 未选中。您的代码 运行 更改后没问题。这是屏幕截图:

2。另一个解决方案是使用 layers.Raycasting 但忽略 Player layer.Before 你这样做,确保创建一个图层调用 Ground 并将你的地面游戏对象放入 Ground 层,然后创建另一个名为 Player 的层并将你的玩家放入 Player 层。我们现在可以使用 bitwise 运算符从光线投射中 排除 Player 层。

现在,假设玩家层数为9。下面的代码应该可以解决您的问题。

public int playerLayer = 9;
int layerMask = ~(1 << playerLayer); //Exclude layer 9
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.down, 0.1f, layerMask);

就是这样。这两个都能解决你的问题。

对于阅读的其他人,下面是无需使用 Physics2D.Raycast 或执行上述所有操作即可轻松检测 Player 何时接触地板的其他方法。

只需附加到 Player

public class Player : MonoBehaviour
{
    public LayerMask groundLayer;
    Collider2D playerCollider;
    bool grounded;

    void Start()
    {
        playerCollider = gameObject.GetComponent<Collider2D>();
    }

    public bool IsGrounded()
    {
        grounded = Physics2D.OverlapCircle(playerCollider.transform.position, 1, groundLayer);
        return grounded;
    }
}

或者您可以使用 IsTouchingLayers.

public bool IsGrounded()
{
    grounded = grounded = playerCollider.IsTouchingLayers(groundLayer.value);
    return grounded;
}