【问题标题】:Unity 2D collision detection with kinematic rigidbody使用运动学刚体进行 Unity 2D 碰撞检测
【发布时间】:2019-05-22 21:24:44
【问题描述】:

刚开始使用 Unity,所以请耐心等待 :) 我们正在构建一个类似塞尔达的游戏 - 自上而下,没有物理/重力,地图的瓦片地图。我们不想使用动态刚体,因为它背后的所有物理特性。

tilemap 有一个带有 CompositeCollider2D 和 Static 刚体的“墙”,我们的玩家有一个 CircleCollider2D 和一个运动学刚体。玩家和墙壁都具有零摩擦的物理材质。

使用运动学刚体进行碰撞检测的最佳方法是什么?我们有几个像 Physics2D.CircleCastAll 这样的概念,但最终我们的玩家卡在墙上或卡在角落里(玩家应该在角落里平稳移动)或卡在两个重叠的碰撞器中。

我们想出的最佳解决方案是这样(玩家有时仍会遇到碰撞器,但至少不会再被卡住了)。

// MoveDirection is the movement input
movement = MoveDirection * Speed * Time.deltaTime;

List<RaycastHit2D> results = new List<RaycastHit2D>();
List<RaycastHit2D> resultsX = new List<RaycastHit2D>();
List<RaycastHit2D> resultsY = new List<RaycastHit2D>();

if (movement.x != 0)
{
    actorCollider.Cast(new Vector2(movement.x, 0), filter, resultsX, movement.magnitude);
    results.AddRange(resultsX);
}

if (movement.y != 0)
{
    actorCollider.Cast(new Vector2(0, movement.y), filter, resultsY, movement.magnitude);
    results.AddRange(resultsY);
}

foreach (RaycastHit2D hit in results)
{
    Vector2 normal = hit.normal;

    float projection = Vector2.Dot(movement, normal);

    if (projection < 0)
    {
        if (hit.distance > 0)
        {
            projection += Mathf.Max(hit.distance - 0.01f, 0);
        }

        movement -= projection * normal;
    }
}

// move player
newPosition = body.position + movement;

// make sure the player is positioned at pixel perfect positions
newPosition.x = (Mathf.Round(newPosition.x * 16) / 16);
newPosition.y = (Mathf.Round(newPosition.y * 16) / 16);
body.MovePosition(newPosition);

// this part moves the player back in case it is in a collider.
List<Collider2D> colliderList = new List<Collider2D>();
if (actorCollider.OverlapCollider(filter, colliderList) > 0)
{
    foreach (Collider2D hit in colliderList)
    {
        var distance = hit.Distance(actorCollider);
        body.MovePosition(body.position + (distance.normal * Mathf.Abs(distance.distance)));
    }
}

播放器设置:

墙壁设置:

不知何故,它仍然感觉太复杂了。这是进行碰撞检测的最佳方法还是我们完全错误地做错了并且有更好/更简单的方法?请记住,我们希望能够以某种方式绕过直角而不会卡在它们上面。并且有重叠的碰撞器或彼此相邻的碰撞器。

感谢您的宝贵时间!

【问题讨论】:

  • 您上传了 2 次相同的图片

标签: unity3d collision-detection game-physics game-development


【解决方案1】:

如果我理解您正在尝试正确执行的操作,那么您的操作过于复杂了。如果您的场景中有两个带有碰撞器的对象,如果您让 Unity 为您执行移动,它们将不会“相互碰撞”。

我的意思是,与其使用 Player.Transform.position = new Vector3(Player.Transform.position.x + 1, Player.Transform.position.y, Player.transform.position.z) 之类的东西来执行您的运动,您可以将 RigidBody2D 组件附加到您的播放器并使用 myRigidBody = GetComponent&lt;RigidBody2D&gt;(); 之类的东西在您的代码中引用它然后在您的运动功能中,您只需使用myRigidBody.velocity = new Vector3(moveSpeed, myRigidBody.velocity.y, myRigidBody.velocity.z) 之类的东西来移动播放器。然后,只要玩家有一个对撞机,你希望它不进入的对象有一个对撞机并且没有一个对撞机有'isTrigger'打勾,那么玩家就不会进入任何风景。

我确实注意到了您的“像素校正”类型代码,虽然我自己从未使用过类似的东西,但我认为您可以在这些东西上使用它,它会正常工作。

【讨论】:

  • 是的,当我将我的玩家的身体类型设置为“动态”时,这很有效,但如果它是运动学的,他只会走遍所有东西(除非我错过了什么,我已经添加了带有设置的图像播放器和墙壁)。动态刚体的问题是你可以绕过敌人和所有非静态的东西,我们不希望这样。
  • 嗯,再想一想,在玩家和角色上使用动态刚体并执行 Physics2D.CircleCastNonAlloc 以防止它们相互碰撞可能是个好主意...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 2020-04-15
  • 2021-09-25
相关资源
最近更新 更多