1
\$\begingroup\$

I'm practicing Unity by developing a 2D game where the player has to stack tetrominoes falling from the sky. The problem I've ran into is that upon a 90 degree rotation of the falling piece, the piece sometimes overlaps with the existing tower causing two pieces to be stuck together.

I would like to check if this overlap will happen before rotating my piece.

I'm aware that such a problem would probably be solved by rotating a copy "shadow" object and checking for collision and yet I have found no way to check if an object is colliding directly after spawning it. I'm also aware of the Physics2D.OverlapBox method but I'm really looking for a way to predict collision with a more complicated 2D shape.

Current code for the shadow collider attempt:

GameObject shadow = new GameObject();

shadow.transform.position = currentTetrisPiece.transform.position;
shadow.transform.rotation = currentTetrisPiece.transform.rotation;

PolygonCollider2D shadowCollider = shadow.AddComponent<PolygonCollider2D>();

PolygonCollider2D currentCollider = currentTetrisPiece.GetComponent<PolygonCollider2D>();
shadowCollider.isTrigger = true;
shadowCollider.points = currentCollider.points;

shadow.transform.RotateAround(rotationPoint, new Vector3(0, 0, 1), 90);

Physics2D.SyncTransforms();

bool collided = shadowCollider.IsTouchingLayers();

if (!collided)
{
    currentTetrisPiece.transform.RotateAround(rotationPoint, new Vector3(0, 0, 1), 90);
}
\$\endgroup\$
8
  • \$\begingroup\$ If you want a more complicated shape then you need a collision detection for such a shape. Mesh collider (Polygon Collider for 2D) should work. Could you also elaborate on this "no way to check if an object is colliding directly after spawning it"? Your thoughts on solution are valid, I am not sure what to recommend exactly, rotating a shadow collider or using a collision function is the best in my opinion. Some hacks may be possible depending on the gameplay but as a general solution collision detection is good. \$\endgroup\$ Commented Dec 26, 2021 at 0:15
  • \$\begingroup\$ "more complicated 2D shape" What is a tetromino if not a collection of boxes? What do you perceive is making this more complicated than what OverlapBox can do for you? \$\endgroup\$
    – DMGregory
    Commented Dec 26, 2021 at 0:52
  • \$\begingroup\$ @DMGRegory's suggestion to using the OverlapBox on the children seems like a very fine solution to my problem with tetrominoes but I'm still wondering how one would achieve the same result when the object has a complicated Polygon Collider. \$\endgroup\$ Commented Dec 26, 2021 at 20:49
  • \$\begingroup\$ @Candid Moon Max the problem i ran into with the Shadow collider was that there seemed to be no way of checking for triggers after instantiating the triggger collider in the "endspot" of the 90 degree rotation. \$\endgroup\$ Commented Dec 26, 2021 at 20:55
  • \$\begingroup\$ @Oliver what barrier did you observe to checking for overlapping triggers using eg. OverlapCollider? \$\endgroup\$
    – DMGregory
    Commented Dec 26, 2021 at 22:57

1 Answer 1

0
\$\begingroup\$

From: Collider2D.IsTouchingLayers

"It is important to understand that checking if colliders are touching or not is performed against the last physics system update i.e. the state of touching colliders at that time. If you have just added a new Collider2D or have moved a Collider2D but a physics update has not yet taken place then the colliders will not be shown as touching. The touching state is identical to that indicated by the physics collision or trigger callbacks."

The physics loop doesn't know about the change when you check for collision. You should wait for a physics update or simulate it.

Physics.Simulate - for simulating physics manually.

You should also check out this thread that started with the same problem as yours: Instant Collision Checking.

Rigidbody.SweepTest - This is probably what you are looking for, but the problem there is no analog for rotation. Someone here: SweepTest for rotation came up with a hack to achieve this but I haven't tested it myself, so I will copy it here.

Collider2D.Cast - a 2D alternative to SweepTest.

[by "forcepusher"]

var rigidbodyCompoennt = GetComponent<Rigidbody>();
var initialRotation = rigidbodyCompoennt.rotation;
rigidbodyCompoennt.rotation = rotationSweep;
var sweepHits = rigidbodyCompoennt.SweepTestAll(new Vector3(0f, 0.01f, 0f));
rigidbodyCompoennt.rotation = initialRotation;

The main idea is to rotate your object, then after a sweep test with unnoticeable movement - reset rotation back to normal.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This answer solved my problem although I did end up using Rigidbody2D.Cast which is just the 2D equivalent of Rigidbody.SweepTest. \$\endgroup\$ Commented Dec 27, 2021 at 22:45
  • \$\begingroup\$ @OliverHvam that is awesome, thanks for sharing your solution, I will update the answer to include it. \$\endgroup\$ Commented Dec 28, 2021 at 20:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .