2D碰撞来自单一方向



我已经学习了一点Unity,同时我已经使用OnCollisionEnter2D函数使我的玩家精灵与地面碰撞:

private void OnCollisionEnter2D(Collision2D collision) {
if (collision.gameObject.tag == "Ground") {
isGrounded = true;
}
}

如果我和玩家一起跑步,并与带有地面标记的物体发生碰撞,则会假设玩家因碰撞而停飞。有没有办法限制OnCollisionEnter2D涉及单一方向?即,当玩家摔倒时,系统可以将其解释为在地面上(玩家的底部抵住地面物体的顶部(

查找碰撞。GetContacts文档。它返回所有与碰撞器碰撞的点。

用法示例:

private void OnCollisionEnter2D(Collision2D collision)
{
ContactPoint2D[] allPoints = new ContactPoint2D[collision.contactCount];
collision.GetContacts(allPoints);
foreach (var i in allPoints)
{
Debug.Log(i.point);
}
}

如果所有的i.point.y < transform.position.y,那么你与地面相撞

所以我借用了Adrien G.的评论,检查了对撞机的边界,比如

private void OnCollisionEnter2D(Collision2D collision) {
Collider2D collider = collision.collider;
Collider2D otherCollider = collision.otherCollider;
if (collision.gameObject.tag == "Ground") {
if (otherCollider.tag == "Hero") {
if (!isHorizontalCollision(otherCollider, collider)) {
isGrounded = true;
isFalling = false;
isJumping = false;
horizontalCollision = false;
} else {          
horizontalCollision = true;
if (isBottomCollision(otherCollider, collider)) {
horizontalCollision = false;
}
}
}      
}
collisionCounter++;
}

由于我的玩家有Hero标签,我确保通过它限制对vars的访问。水平碰撞抓住了每个碰撞器的边界:

private bool isHorizontalCollision(Collider2D collider1, Collider2D collider2) {
int c1RightEdge = (int) collider1.bounds.max.x;
int c1LeftEdge = (int) collider1.bounds.min.x;
int c2RightEdge = (int) collider2.bounds.max.x;
int c2LeftEdge = (int) collider2.bounds.min.x;
return (c1RightEdge == c2LeftEdge) || (c1LeftEdge == c2RightEdge);
}

这意味着,如果每场比赛的边界向左或向右,就会发生水平碰撞,因此球员不应该被标记为接地或不再摔倒或跳跃。但在我的情况下,我使用这个进行水平移动:

float horizontalInput = Input.GetAxis("Horizontal");
.
.
.
body.velocity = new Vector2(horizontalInput * speed, body.velocity.y);

英雄仍然会移动,就好像试图穿过一个碰撞的水平物体。所以我将速度变化封装在一个块中:

if (!horizontalCollision) {
body.velocity = new Vector2(horizontalInput * speed, body.velocity.y);
.
.
.

但这会使英雄摔倒在地后冻结,因此它将无法行走,除非它在没有水平碰撞的情况下跳跃和摔倒。为了解决这个问题,我实现了一个isBottomCollision函数:

private bool isBottomCollision(Collider2D collider1, Collider2D collider2) {
int c1BottomEdge = (int) collider1.bounds.max.y;
int c2TopEdge = (int) collider2.bounds.min.y;
return c1BottomEdge == c2TopEdge;
}

这与水平碰撞基本相同,但要检查玩家的底部边缘与碰撞器的顶部边缘。如果它们匹配,则碰撞是从底部开始的,因此horizontalCollision布尔值设置为false,使英雄能够再次运行。

您可以使用Collision.relativeVelocity来实现这一点。

假设地板在y方向上是静态的,为了检查玩家是否从顶部与地板碰撞,你可以检查玩家与地板之间碰撞的相对速度在y方向是否低于0:

void OnCollisionEnter(Collision collision)
{
if (collision.relativeVelocity.y < 0)
//the collision came from the top 
}

看看:https://docs.unity3d.com/ScriptReference/Collision-relativeVelocity.html

最新更新