Why can't we have functional collision?

I have a set of extremely annoying problems with my 2D platformer, and they all come down to problems with Unity’s collision.

The first problem is that if I have a ground surface that is made up of multiple colliders, my player will randomly get stuck on the flat surface.
For example, I have a simple, flat surface, made up of several repeating tiles, and each of those tiles has its own collider. Mathematically, this is just a flat surface. But somehow, my character can get snagged walking across such a surface. It’s random, and some days it seems fine and other days it gets snagged like crazy.

What’s happening here is that the box collider around my character is detecting a collision between the side of its collider and the side of the ground’s collider. This should never happen, but it does. I’ll be walking across a flat surface, every tile using the exact same size for its collider and all at the exact same location in Y, and then suddenly I’m stopped like I just walked into a wall.

The forces me to restrict how I create my levels. I have to use one collider for an entire ground surface. I can’t have a flat surface that has any kind of special tile in center or at the edge, or else the player might snag on it. And I can’t simply have a collider as part of the same sprite I’m using for a tile, so I have to build my level’s visuals separate from my level’s collision, which makes it much more time consuming to make changes to a level.

The only way to resolve this problem is to have a rounded-bottom collider for my character. But this is even more limiting, because then my character can’t stand on the edge of a platform, or else they will just slip off of the rounded bottom. And being able to stand on the edge of a platform is a pretty important facet of a platformer, or else you can’t have tricky jumps, and thus can’t have, well, platforming.

But this isn’t even the extend of Unity’s collision problems. Following the examples we are given, I added some empty objects to my character and use their transforms as points to check to see if there is ground underneath my character. To make sure I am checking the whole area that the player can stand on, I have one in the middle, and one on either edge. Thus I can tell if my character is grounded, even if they are only just barely on the edge of a platform.

Except that when I stand on the very edge of a platform, the very smallest sliver I can manage, my character does not think they are on ground, and they start their falling animation and can’t jump.
I have set up the amounts exactly for how bug of an area the groundcheck checks for ground, exactly where the ground check is, and exactly how big the character’s collision is. Despite being mathematically perfect, I still have the tiniest sliver where the ground checks fail to see ground but the character is still held up by the platform.

At this point I can move the groundcheck by the smallest fraction possible, and then it is checking past the character collision. When this happens, when I jump while standing next to a wall, the groundcheck continually registers that I am still grounded, and will let my character fly upwards for the entire height of the wall.
This is due to how I have to arrange my character’s motion; since I can’t get the player’s movements to work exactly how I need them with the default physics, all calculations for stuff like gravity is handled within the player script. And logically, we don’t want to push the player down if they are grounded. So if the groundcheck says that they are grounded when they stand next to a wall, the player has no gravity if they are next to a wall.

But I shouldn’t have that problem anyway; I have my groundchecks set mathematically exact, but there is no point where I can have the groundcheck exactly line up with the collision.

The collision in this engine just doesn’t quite handle its edges properly.

I understand your frustration. I wrestled with collisions a lot when I first decided to give Unity a try.

I don’t have any issues with collision detection now because after much experimentation I ended up with a couple methods that work: Raycast and most recently OverlapArea. Initially I relied heavily on Raycast simply because I was not aware that OverlapArea even existed (and possibly it didn’t when I first got Unity… not sure). I am slowly converting my current game over from Raycasts to OverlapArea because really all that is needed is a simple OverlappingRect form of collision detection and OverlapArea handles that. I’d recommend trying OverlapArea and see if you find that easier and more reliable to work with.

Beyond that, honestly it sounds like the biggest cause of the problems you are having is from relying so much on the colliders. It sounds like your game is tile based? So is mine. The game world is designed in a tile map editor (SpriteTile) and the whole world is just a large tile map.

I do not have any colliders on any of the tiles simply because I have made tile-based games in the past and just used the tile map data itself for the collisions. That is one of the benefits of using a tile map to begin with! It contains not only the data for what to display but also the data for how the tile can be interacted with (or at least is easily obtained by mapping the tile ID into a lookup table, enumeration of flags or whatever that specifies the properties of the tiles).

So, I’d recommend dropping the colliders completely and simply examining the tile map. When your player moves down just cast a ray (not a Unity ray but I mean just make a little function that performs a quick loop down the distance your player is moving and if no tile floor is found return the distance passed in, otherwise if a tile floor is found return the distance iterated minus 1 pixel). Now you know exactly where your player’s feet should be. In reality, my own function takes the width of the sprite into account, the left side and right side, the width of each tile, and then performs multiple checks horizontally in each loop to account for the range of tiles below the player.

Here is a platform game demo project I made last summer that served as a test of these things. The tiles have no colliders on them. The rocks, player and snakes casts out rays to detect collisions with the tiles.

http://garsgames.com/Unity3D/Games/PlatformGameDemo/
Instructions for how to play can be found right beneath the webplayer.
Game starts out paused so press P to begin playing.

No messing with colliders just normal straightforward game programming working with a proven data structure: the tile map. Of course, if you have a need for some reason to use Unity colliders then certainly do so. Perhaps the OverlapArea method will work for you.

2 Likes

Hey Marscaleb

Here is some more on the tile colliders issue and to build further on GarBenjamin’s recommendation of OverlapArea(). I am assuming that you are using 2D components.
Instead of having a BoxCollider2D or CircleCollider2D for the player, you can define a PolygonCollider2D.
Here is an set up example:


This way you can avoid making the player fall at the very edge. Make sure the bottom vertex is very slightly angled.
When it comes to the ground checking, use two empty objects to call Physics2D.OverlapArea().

Read here: Unity - Scripting API: Physics2D.OverlapArea

Simulate the shape of a Rectangle with the two points. Also leave some space between the PolygonCollider2D and the Ground Check Rectangle so you can avoid the wall grounding problem.
Don’t forget to add the LayerMask to define what is considered as ground.

biowinter:
I actually tried using the OverlapArea for my groundcheck at one point, hoping it might improve the situation. It didn’t change anything, so I went back to the three-point system just so that I wouldn’t have to revise the code for all of my characters.

The polygon collider looks interesting, but unless Unity 5 has revised the editor for those, it would be a major pain to custom build those for each character. You can’t get very precise with those.
But that shape is a very good idea that would (probably) get around all of those problems.

GarBenjamin:
The tilemap check is a great idea, and I thought about doing that before, but I don’t have the time to build a system that complex and get it to work properly, and I doubt there is one I can buy that is both within my price range and won’t take me a week to get to work with my existing code.
Not that I’m opposed to the idea, mind you, it is a great idea. But that is something that requires a LOT of effort to build properly.

I guess it depends on what a person is used to. I don’t care for all of this physics, animator, colliders and so forth. I find it easier to just code the stuff up myself because it is stuff I have done countless times in the past. Well, actually I do use the colliders. Hate the collision events. In that platform project I was still using them and I find them a real pain in the ass. All I want from a game API / engine is the ability to load graphics, sounds & music and then draw stuff where I want and play sounds when I want.

Anyway, if you decide to implement a tile collision system feel free to message me and I should be able to give you some help with it even if it is just describing how I implemented it.

I am thinking there has to be some way around it though based on all of the platform games I have seen developed in Unity. But maybe they all just create colliders around sections of tiles instead of one collider per tile.

Well I can figure out how to implement it in my mind.
You’d need some sort of tilemap object that stores all the data. It would need a list of all the tiles that could be drawn into the tilemap, and each one of those tiles contains data for what image it uses, what kind of solidity or collision it has, and possibly a few other characteristics, as well as other characteristics mapped out to specific tile locations that are independent of the tile, like flipping/mirroring. And you would need some sort of editor to be able to set those tile qualities and draw the map.

And then you would need a system so that your actors could check the tilemap for solidity data. And you would need to write all of your own code for movement and physics, since you probably couldn’t rely on the existing rigidbody systems to handle velocity.

If I started with someone else’s tilemap editor, that would probably take me one to two months.
I really don’t think I can claim that my levels are going to take an extra two months worth of time to make separate visuals and collision. Not for the scope of this game, anyway. And I’m not really doing anything complicated enough to warrant the need for such custom systems.

As I had I said, I like the idea. But even so, it’s not practical for me.
I honestly don’t see why Unity didn’t come with a tilemap editor built-in. If you’re going to put a focus on 2D capability, to the point where you create a whole alternate physics system and sprite animation package, you’d really think they would put in an easily-extendable tilemap editor.
But by the same token, I have no idea why they wouldn’t have a collision system that works properly with squares.

1 Like

@Stv3D , did you actually use that design you showed, or did you just think it up on the spot?
I’m very interested in this design, but I’m worried about practical implementation. Ideally if I stand on an edge beyond the ground check, I would slide off on those angled sides, so I could not stand on that extreme corner.
But how precise does that have to be? How sharp of an angle? When I’m editing my collider, the thing won’t be visible if I zoom in to close.

@Marscaleb , I am currently using that design, of course is not perfect yet it reduces 80-90% of the jittery and does not get stuck through tiled BoxColliders2D. Since the angle of depression is minimal, there is little to no sliding even if standing on the edge of the collider.
The side “bevels” are meant for interaction with other surfaces such as spheres, expanding or contracting those as needed for sliding. Reduce them to right angles to avoid sliding or even remove them if necessary.
How precise does it have to be? As long as the middle vertex does not make a straight angle and is not too prominent that it creates jittery like a CircleCollider2D.

Physics calculations are approximate and use floating point, and sometimes due to gravity or rebounds etc it can make objects penetrate surfaces even if logically they shouldn’t. There is a physics setting to do with the penalty for minimum penetration depth, which you can play with.

Also what I would do simply is having a box collider which spans most of the width of the player, but not all the way to the left and right edges. Then add 2 very small circle colliders in the lower 2 corners, to smooth off the collision profile. Maybe another box collider horizontally across the middle of the player to fill out the extra space. This way he can stand mostly on the end of platforms without falling off unless he is really barely on the edge, and the circles will make sure the player smoothly moves over the corners of box joints. Then you don’t need the raycast mess.

Well, precise enough that I don’t run into issues.
I suppose I would be fine with eyeballing it as long as it is mostly right, but that drafter inside me gets really irritated and worried when I can’t declare an exact value. I hate sloppy work; sloppy work makes you run into more problems later on.

@imaginaryhuman_1 That sounds like an intriguing idea. The only problem I can see with that is getting my crouching to work with two box colliders. Right now, to get my collision to change when the player crouches, I have my script search for a box collider when the script starts, and when the player crouches or stands up, I adjust the variables for that collider. But if I have multiple box colliders, I have no way to make sure that I am finding the correct one.

Where do I find this minimum penetration depth to play with?

in the physics settings. up in the menus.