I’ve been tinkering with Unity’s 2D tooling since it was officially released in v4.3. With each new version we see some improvements in the 2D tools and workflow, but alas it’s far from perfect and as a result getting things to work the way you want is all about trial and error.
One thing I have learnt quickly about Unity is that there are many ways to approach a problem, each with their own pros and cons. Sometimes you need to get creative with your solutions. Player colliders in Unity are one such area that that can be a struggle. Some of the problems commonly experienced when making tile based 2D games is player objects getting stuck on floors, walls and ceilings.
Below I will outline some of the problems, why they occur, and then share with you my approach, which although isn’t bulletproof, works for me.
Ray Casting is another approach which can work well, but has its own challenges to overcome. It will not however be the focus of this post.
Note* I am using Mario sprites simply for illustrative purposes. The real Mario was created long before Unity, and obviously used a different (better) system.
Getting stuck on the floor
Using a box collider with a simple Mario sprite seems like the perfect way to handle collision, but unfortunately Unity struggles with this setup and its quite common for your players collider to get caught on floor tiles that also have their own box colliders.
This has nothing to do with pixel spacing between tiles and will happen even if you have your tiles snapped together perfectly. I believe the problem comes from floating point values which are the source of many problem in various parts parts of the Unity workflow.
In some cases it may be possible to create one massive box collider for the whole floor or platform, this is a pretty limiting approach though, especially in a tile based world which can have many platform sizes.
Consider also that in a game like Mario, blocks are destructible, so the collider must be removed with the block. This would not be possible with one large collider spanning the size of a platform.
Using two circle colliders is a popular setup which I have seen used quite often in other tutorials and example projects. And though it eliminates the problem with floor stickiness, it creates new problems due to limited accuracy when jumping onto platforms (the player will roll off edges). Once again, it depends on your games requirements. If your game is a downhill runner, then sure circle colliders might do the trick, but to use a Mario platformer as an example requirement, you would need something more robust.
Hybrid Collider Setup
Which leads us to the setup which I have found works for me. It is a combination of box and circle colliders positioned in such a way to avoid obstacles getting ‘caught’.
You will need to test the sizing s against walls and floors, and make little adjustments till it feels right. Remember folks, if it feels right it is right. 😉
Remember, this approach isn’t fool proof, but it got me as close as I needed without using ray-casting.
One final step which is quite important. Add a low friction aka ‘slippery’ Physical Material to your box collider. This will stop it getting caught on walls when you are pressed up against them and attempt to jump.
Creating a PhysicalMaterial for a 2D game is easy, just right click in your project panel, and select create > Physical 2D Material
Give the Physical2D material a name like ‘Slippery’ then double click it and lower the friction settings to 0.
Finally to apply it to your player’s box collider, click on your player and drag the Slippery material to the ‘Material’ slot under the box collider section in the players property panel.
I hope you have found this info useful, if so consider following me on twitter @johnstejskal or sharing this post!
If you have any questions or suggestions drop them in the comments below.