【发布时间】: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