- Home /
Precise Collision Detection with Rigidbody2D.Cast
Greetings.
My question is if Rigidbody2D.Cast can be used for pixel-perfect collision checking. I recently came across this blog which discusses a method for collision detection in 2D games. https://zackbellgames.com/2014/10/28/understanding-collision-basics/
I desired to recreate this collision detection in unity by replacing place_meeting with a implementation of Rigidbody2D.Cast. Note that the pixel to unit size for all objects is 1:1. The following is my attempt.
However, I seem to be getting collisions both vertically and horizontally when the object is pressed against one or the other. In other words, the object counts as blocked on both axis when only blocked on one. I'm struggling to determine if this is a result of my own implementation error, or if Rigidbody2D.Cast simply cannot be used for pixel-perfect collision. Any help or advice would be welcome.
Thank you!
Physics Object
public class PlatformerPhysicsObject : MonoBehaviour
{
//Modifiable Values
public float gravityModifier = 1f;
//Velocity and Position
protected int vy = 0;
protected int vx = 0;
protected int x = 0;
protected int y = 0;
// Physics Body and Collider
protected Collider2D col;
protected Rigidbody2D body;
protected ContactFilter2D contactFilter;
void Awake()
{
body = GetComponent<Rigidbody2D>();
col = GetComponent<Collider2D>();
updatePosition((int)body.position.x, (int)body.position.y);
SetupContactFilters();
}
protected virtual void ComputeVelocity()
{
}
void applyGravity()
{
vy += -1;
}
void FixedUpdate()
{
applyGravity();
ComputeVelocity();
Movement();
}
void Movement()
{
for (int i = 0; i < Mathf.Abs(vy); i++)
{
if (!placeMeeting(x, y + (int)Mathf.Sign(vy)))
{
y += (int)Mathf.Sign(vy);
updatePosition(x, y);
}
else
{
vy = 0;
break;
}
}
for (int i = 0; i < Mathf.Abs(vx); i++)
{
if (!placeMeeting(x + (int)Mathf.Sign(vx), y))
{
x += (int)Mathf.Sign(vx);
updatePosition(x, y);
}
else
{
vx = 0;
break;
}
}
}
void updatePosition(int xi, int yi)
{
Vector2 pos = new Vector2(xi,yi);
body.position = pos;
}
bool placeMeeting(int xi, int yi)
{
RaycastHit2D[] result = new RaycastHit2D[8];
Vector2 direction = new Vector2(xi,yi);
int count = body.Cast(direction.normalized, contactFilter, result, 1);
return (count > 0);
}
void SetupContactFilters()
{
contactFilter.useTriggers = false;
contactFilter.SetLayerMask(Physics2D.GetLayerCollisionMask(gameObject.layer));
contactFilter.useLayerMask = true;
}
}
Player
public class PlatformerPlayerController : PlatformerPhysicsObject {
public int maxSpeed = 7;
public int jumpTakeOffSpeed = 100;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
protected override void ComputeVelocity()
{
vx = (int) Input.GetAxisRaw("Horizontal") * maxSpeed;
if (Input.GetButtonDown("Jump"))
{
vy = jumpTakeOffSpeed;
}
else if (Input.GetButtonUp("Jump"))
{
if (vy > 0)
{
vy = (int) ((float) vy * 0.5f);
}
}
}
}
Answer by DunderAxel · Apr 01, 2019 at 02:24 PM
@Ponderline - Did you figure out a solution for this issue?