- Home /
Unity physics 2d crack between colliders.
I have a ball and multiple of alligned blocks. When the ball moves on the blocks, sometimes the ball collides with one of the blocks as you see in the picture. The ball was moving left to right and when at the joint of two blocks it sometimes bumps. As if there was a height difference, like a little crack. This does not happen with all of the joints. It occurs randomly. The blocks were created and alligned by code so I don't see why it has a difference in height. Only thing that I could think of is somewhere in floating points??
Below is the code from the "Block Manager" gameObject where it creates all the blocks. I would really like to know why this is happening for sure, and a solution would be even greater.
using UnityEngine;
using System.Collections;
public class BlockManagerScript : MonoBehaviour {
public GameObject block;
// Use this for initialization
void Start () {
for (int i = 0; i < 200; i++) {
GameObject blockCopy = Instantiate (block);
blockCopy.transform.SetParent (transform);
Vector3 position = block.transform.position;
position.x += block.GetComponent<SpriteRenderer> ().bounds.size.x * (i + 1);
blockCopy.transform.position = position;
}
}
// Update is called once per frame
void Update () {
}
}
One more point Xon, it's worth noting in general terms that you often SI$$anonymous$$PLY DO NOT USE PHYSICS, AT ALL, in "puzzle" type games.
You do them, let's say, "logically". A question that comes up endlessly on this site is "how to tumble a cube in a puzzle game!" (OPs start off by trying to use the physx engine and applying toruqe, etc)
example,
http://answers.unity3d.com/answers/1111309/view.html
Often you just don't, at all, use the physics engine to do "puzzle-like" games.
Note that I have no idea what the "feel" of your game is, so indeed you may want a "physic feel", and that's great. But just a warning to future googlers who are making "puzzle-type" games, often you just absolutely don't use any physics engine.
In your example, you would just move the cube "knowing" that levels exist at certain places, etc.
Physics $$anonymous$$aterial 2D worked for me.
- Create a Physics $$anonymous$$eterial 2D.
- Set friction is zero
- Assign it into colliders (don't need for player)
Hope it can help you
Answer by Alamarche · Dec 21, 2015 at 04:32 PM
First ill start off by saying you should probably have a CircleCollider on the ball rather than a BoxColldier. The sharp edges are getting caught in between the blocks. If that still doesn't work then do this:
Keep a reference to the first block you make (You should probably hand place this one in the scene so that you can easily reference it). From there, whenever you create a new block, you'd just increase the size of the first blocks collider rather than just making a new one every time. This would make one large collider with no gaps and everything should be smooth.
I've tried this before I wrote this question. It does help a bit on the problem but the way circle colliders behave in edges of platfroms just did not fit my game design. And even if you do the ball kind of jitters at joint, it moves the ball only like 0.001 units but it still means that its not alligning right, and its just that I would like to know why this is happenning and know a way to fix bug(?). Anyways thanks for the reply :- ). Also, about your second suggestion, this seems like it could be an way around for my game... hmm.. I'll give it a try. Thanks, wonder why I never thought of it.. ps, come to think of it now I really can't do that because the reason why I am making the ground with multiple seperate pieces is because at some point I need them to sperate with each pieces with there own collider, making the illusion of the ground breaking.
Answer by wibble82 · Dec 21, 2015 at 05:10 PM
The problem you are seeing comes from the fact that a physics engine in a game doesn't see the world like we do :)
You and I can see a set of boxes next to each other, perfectly aligned, with an object moving along the surface. We therefore conclude that it should never bounce up, as it moving along something flat.
To the physics engine however, each of those boxes that make up the floor are entirely independent objects with which the sliding object can collide. Each frame it works out which ones the sliding object might collide with, and attempts to approximate what the correct physical reaction would be if it did. What you are seeing is an inconsistency when your sliding box is sitting on the surface of 1 box, but touching the corner of another. If the engine processes the surface first, it'll probably work fine, but if it happens to process the corner collision first, you'll see a blip!
This problem is made worse by the 'discontinuity' in your box-box collision. As your surface object is a box, the results from:
its lower edge hitting the edge of the box below it
its bottom right corner hitting the top right corner of the next box
Are substantially different - the first simply holds the box up, the 2nd would apply some force up and to the left.
Using a circle collider will certainly help. Technically the physics engine still has the same problem (it doesn't know which box you hit), but there is only 1 point in time at which a circle is potentially hitting 2 boxes - when it is directly above both their corners. In this situation, both boxes would agree that the correct collision response was simple to push the circle upwards, so you wouldn't see a blip. This might break down as you get to high speeds (as it's all approximations), but at suitably low velocities it'd probably be perfectly stable.
If you must use a box for your surface object, then you will either need to:
Use 1 large box collider, instead of lots of small ones for the floor
If you can't represent the floor with 1 box collider, you'll need to generate an edge collider for it
Note that an edge collider has 'connectivity' information (each edge knows about other edges), so it can handle the situation in which an object could hit multiple edges more elegantly.
-Chris
of course as Chris says the answer is
"Use 1 large box collider, ins$$anonymous$$d of lots of small ones for the floor"
you simply can not "sit colliders together" like you have done
"You and I can see a set of boxes next to each other, perfectly aligned, with an object moving along the surface."
Actually Chris if you literally try this, with very sharp boxes (such as casino dice, which have a very sharp cut), in fact ................ it will do exactly whay PhysX is doing, ie, you WILL IN FACT CATCH THE EDGES!
It's that simple. You are right that the OP could use a sphere collider. But more likely you'd just make a box collider with "rounded edges". That is to say, essentially just add little sphere colliders (or perhaps capsule collider) at the edges.
In some cases you just add another box collider at 45 degrees (sort of a "sawn-off edge" if that makes sense). It's commonplace to have to do this for objects, when you "catch an edge"
Essentially this is the right answer.
Answer by InDNA · Dec 22, 2015 at 09:01 AM
Hmm.. Maybe your player object is being rotated when you move. It looks like your player is at a slight angle in the screenshot, so this may be a square wheel situation. Every time a corner of the square hits the ground, it bumps up do to an uneven rotation. If this were the case, it would probably still make the player object bob up and down, even when using a circle collider. This could be fixed by freezing your player's z-axis during movement.
If that's not it, i'll have to keep thinking man.
You could also try overlapping your block objects a little when you position them. This isn't really best practice as far as I know, but it may tell us if gaps between blocks are even the issue here.
// Overlaps blocks by 1%
position.x += (block.GetComponent<SpriteRenderer> ().bounds.size.x * 0.99f) * (i + 1);
I tryed overlaping as well as spacing the blocks before but it didn't help : -( I figured out a way to solve my problem and posted on this page have a look and tell me what you think : -)
Answer by xon235 · Dec 22, 2015 at 09:04 AM
Okay I think I found a way to do this. I couldn't do it the way you guys described because of my game design (1. The blocks are only at the same height for test purpose and in the real game it will be randomly determined. 2. At the end of the platform I need it to sperate like its breaking, so I couldn't use one collider for all multiple blocks).
Anyways the way I handled it was, at BallScript's awake method, I made code to add four sperate edge colliders for each of sides in box colliders with little shorter length and to disable box collider at runtime . I call this cutting the corners. (corner cut).
Below is the Awake method in BallScript.
void Awake () {
rb = GetComponent<Rigidbody2D> ();
//get Boxcollider2D points
BoxCollider2D bc = GetComponent<BoxCollider2D> ();
Vector2[] points = new Vector2[4];
//Clockwise starting from left top
points [0] = Vector2.zero;
points [0].x -= bc.size.x / 2;
points [0].y += bc.size.y / 2;
points [1] = Vector2.zero;
points [1].x += bc.size.x / 2;
points [1].y += bc.size.y / 2;
points [2] = Vector2.zero;
points [2].x += bc.size.x / 2;
points [2].y -= bc.size.y / 2;
points [3] = Vector2.zero;
points [3].x -= bc.size.x / 2;
points [3].y -= bc.size.y / 2;
//add EdgeCollider
edges = new EdgeCollider2D[4];
Vector2 pointA;
Vector2 pointB;
//Clockwise starting from top
edges [0] = gameObject.AddComponent<EdgeCollider2D> ();
edges [0].points = new Vector2[]{new Vector2(points[0].x + colliderCornerCut, points[0].y), new Vector2(points[1].x - colliderCornerCut, points[1].y)};
edges [1] = gameObject.AddComponent<EdgeCollider2D> ();
edges [1].points = new Vector2[]{new Vector2(points[1].x, points[1].y - colliderCornerCut), new Vector2(points[2].x, points[2].y + colliderCornerCut)};
edges [2] = gameObject.AddComponent<EdgeCollider2D> ();
edges [2].points = new Vector2[]{new Vector2(points[2].x - colliderCornerCut, points[2].y), new Vector2(points[3].x + colliderCornerCut, points[3].y)};
edges [3] = gameObject.AddComponent<EdgeCollider2D> ();
edges [3].points = new Vector2[]{new Vector2(points[3].x, points[3].y + colliderCornerCut), new Vector2(points[0].x, points[0].y - colliderCornerCut)};
//Disable BoxCollider2D since we now have edges
bc.enabled = false;
}
This lets me move smoothly on the surface. This method is really easy on box colliders but I don't think it will be easy to implement the same method on different shapes. But I think this does it for now.
Thank you all for your suggestions and It will be great if someone has a better method to accommodate all kinds of shapes.
Thank you!
You DO sometimes have to use "jagged colliders", you're right.
So, rather than one collider the shape of the box, you use perhaps six colliders that are flat boxes, along each side - perhaps with small gaps at the corners, overlap, or whatever is needed in your situation.
Note you can very simply do this IN THE EDITOR. It's hard to see any need to do it programmatically.
Yes you are right. Also I knew that I could edit edge colliders in the editor but I had to do it with "hand", which being inaccurate. I would have liked to input perfect numbers through a input box, but the input boxes were disabled. Also I just did this programmatically because I didn't want to edit each edge colliders everytime I changed the size or offset etc. Since in my game edge colliders will sum up to something like a box collider, I just gave a box collider 2d component for representation and edits, then replaced it with edge colliders at runtime.
"The blocks are only at the same height for test purpose and in the real game it will be randomly deter$$anonymous$$ed."
It's totally normal that you have to swap back and fore between different types of colliders. So, it might be that you have to swap to "one long" collider when the cubes are perfectly level, and swap to individual colliders when step-like.
Yes true, I just thought that there would be a simpler way to handle it. I will put this in consideration if I come to similar problem with no other ways next time. Thanks you.
hi Xon I'm not sure if you saw my long answer below with the image. (hit reload to see it) To solve the problem of catching edges, you basically just add little round colliders at the corners (or perhaps a long thin capsule, or even just a box collider on a 45 angle). It's completely normal to do this when an object 'catches" Hope this also helps!
I would highly recommend you generate a single edge collider (which contains a list of edges) that represents your 'floor'. This should be a set of edges that represent the surface along which your object should move.
It is perhaps not the simplest approach, and there are many work arounds for this issue, but the most robust solution will be edge colliders for the floor - you can happily still use a box collider for your object (if it is indeed a box!).
As a mentioned breifly in my answer, this is because an edge collider (provided it is just 1 edge collider, with a list of points) contains 'connectivity information'. This is a very common feature of a physics engine - in 3D the same system exists for a mesh collider.
The connectivity information allows the physics engine to identify that the box may appear to hit both the edge it is above, and the corner of the next edge, but because it is aware of both features, it is able to make the decision to take the 'most relavent' edge.
There are certainly other approaches that will get you closer to your desired results - simply using a box with little spheres at the corners will undoubtly be a little better, but if what you're after is the right (and I use that term very loosely!) solution, the edge collider is the correct tool to use for a 2D mesh that represents the floor.
-Chris
As Chris explains, generally the correct solution is definitely that you have to dynamically 'change to' one big collider when you get smaller colliders 'next to each other'
this is completely standard and an "everyday procedure" in vid games.
hi Chris, it is not really realistic to say that using custom colliders will "get you closer to your desired results" :) An absolutely correct and proper solution (such as seen in, oh, Angry Birds) is to use, simply, a collection of colliders to create the approximation you want on a body. It's totally commonplace that on a boxy collider (as in the example I gave of a car) you add let's say a "supplementary" collider (perhaps a sphere or whatever) to deal with those annoying "edge collisions" where you "trip" (which is, indeed, precisely the nature of this QA!)
We may just have to agree to disagree there Fattie :) Certainly in physics there are always many ways to solve a problem. Ultimately a game physics engines is just a groce approximation of real physics, and making the game is as much about 'working with the engine' as it is 'doing things right'!
Generally though in my personal experience, fiddling the collision of the dynamic object to create rounded corners to solve this particular problem (vertex-edge discontinuities in the static object) is not the best way to go. The problem is in the ground, so I would attempt to fix the ground.
Conversely, if my problem was 'my dynamic object is behaving too boxy, and I want it to roll more on the corners', I would fiddle the collision to make it do so.
On Burnout I spent a long time with this exact problem - made worse by the fact that the cars went at 200mph! Although it was a pain, I fixed the terrain (by implementing vertex and edge connectivity data in the form of edge/vertex-cosines) because ultimately that's where the problem was. Fixing the cars would have meant fixing every car - and anything else I ever wanted to move on the ground. And worse, I would have had to explain to other people how to fix it, and get those rounded edges just right! It would have worked, but would be less robust and more work to maintain in the long term.
All that said, game development is often a choice between the 'right' solution and the 'quick' solution. They don't always agree, and the 'right' one isn't necessarily always the right one :)
Answer by Fattie · Dec 22, 2015 at 02:07 PM
Xon, are you aware very simply of adjusting the penetration default?
http://docs.unity3d.com/ScriptReference/Physics-minPenetrationForPenalty.html
"The minimum contact penetration value in order to apply a penalty force (default 0.05). Must be positive. This value is usually changed in Edit->Project Settings->Physics"
Often you can solve these sorts of physics problems by just adjusting that.
Second, note that it is very common when you're dealing with let's say "microphysics" like this, that you need unusually shaped colliders.
There was a suggestion above that you should use a round collider. that's not right, but what you very likely need is a collider that is shaped like a cube, but, has rounded edges - bevels if you will.
(If you think about it, this is exactly what happens in real life. Real life cubes of all types have gently rounded edges, even if only seen at a small scale.)
You should try a collider like this ...
Turn off the box collider and add little balls like that. (You may wish to also leave on the box collider, perhaps inset a little, depending on how your game plays.)
Consider also using long thin capsule colliders along the edges.
It's perfectly normal that you have to use a collection of colliders, to, make an object work in a video game, it is the usual thing. A very simple example is, have you yet done a car game. At first you might just put one box collider for the car. But it's better to have one for the "lower part" of the car up to the lower window line, and then a box for the "upper part" of the car. Further, you might use perhaps a capsule collider for along the front or back. And so on.
in short try basically adding small "rounded, bumper" colliders to your object, and see if you can get what you need.
Don't forget that in real life that dice or box would indeed have rounded edges. You don't have absolutely sharp edges in real life.
Yes I am aware of penetration setting and I tried different values but it didn't help, thank you.
Fattie is correct in suggesting this is an option to look at, but it is ultimately a work around. It will make the problem 'less bad', and maybe if you make the corners round enough it'll even be 'good enough'! Certainly this is elegant in in simplicity ($$anonymous$$imal code changes = good!), so if you can get it to work it's probably the right way to go.
Ultimately though this isn't about real life rounded corners - it is about the results of a separating axis / feature detection algorithm when looking at 2 neighboring boxes. Regardless of whether the corners are rounded, there is a mathematical discontinuity that occurs as a box vertex passes through the boundary in which feature extraction picks up a vertex-vertex or vertex-edge collision, rather than an edge-edge collision.
As long as this discontinuity exists, there is potential for error, manifesting as a 'bump'. It is $$anonymous$$imized if you go to the ultimate 'roundness' - a circle, as mathematically the discontinuity disappears. However the finite nature of the physics engine will still result in discontinuities in the predicted collisions.
Short version: worth a go cos it's simple, but if you need 100% robust, you'll need to generate a proper edge collider as in my other answer.
Hi Chris, it might be surprising but I can absolutely assure you that this is completely standard procedure in basically every vid game, particularly console titles. This is literally how you make video games, unless you go to a mesh collider which is generally not relevant.
Note too that you've said a couple of times that this is an "error" and PhysX is not behaving "like in reality". In fact it is not an error, and is utterly correct. If, for some reason in your game you do want "sharp edges" that cause that type of "jump", you'd do precisely that. Because that's exactly how perfectly square boxes would behave in the real world.
(Note that if the OP happened to want that behavior in his game ... this is precisely what he would do!)
Indeed, almost certainly IN THE REAL WORLD if you were making this product, you would have slightly rounded corners on the PC and ALSO on the floor cubes.
{Indeed note OP, you should probably "round the corners" on the FLOOR CUBES AS WELL.}
It is well worth noting that IN THE REAL WORLD, if you were LITERALLY trying to do this, it's quite impossible. If you get very sharp edges cubes (the best you will be able to get outside of a machine shop is using Vegas-style craps dice, which have quite a sharp edge (it's hardly "sharp" but it's sharp enough for a demo), try lining some up "perfectly" flat as if a floor -- note that it will be totally impossible for you to do that unless you have an incredibly good extremely high precision machine shop bench -- and then slide another one over the top.
Of course .. what will happen? Obviously it will catch every edge.
if you DO NOT want that to happen, with a real-life product, you have to bevel every edge.
Again it might be surprising, but this is precisely how all the video games you play, are made. You typically use a few primitive colliders, to make a shape - "rounding" corners to stop edge catching is a totally typical example! Enjoy!
Well Fattie, as I say above, we'll have to agree to disagree. In my day job I write/use physics engines for PS4 games, though in the past it was other consoles (I did a lot of work on the physics in several of the Burnouts for example). Certainly in these and many other console games I've worked on we were very careful about what problems we solved by fiddling collision, and what problems we solved by other means.
Your answer
Follow this Question
Related Questions
2D 360 degress platformer example needed 0 Answers
Why is this happening? (gif attached) 2 Answers
Velocity from external objects 0 Answers
Replicating genesis Sonic's collision physics 1 Answer
2D platformer feeling 1 Answer