Tiled and collisions in Cocos Creator
If you've tried to figure out how to use collisions with Tiled tiled maps and Cocos Creator probably you had no luck. This is because out of the box, this configuration is unsupported. But there is a way to make it work.
TL;DR
You can find all the code in this repository
How does it work?
The Tiledmap.js
component can be applied on any TiledLayer
node which are sub-layers of a TiledMap
. The script uses Hull.js
and DBSCAN
to generate the collision shapes from the cloud of points of the coordinates of the tiles of that node and apply a PolygonCollider2D
for every cluster of points.
The component has four parameters:
- Debug: if true it will draw the collision shapes in the scene.
- Hull Concavity: the concavity of the hull, the higher the value the more concave the hull will be. You can leave it at 1.0.
- Neighbour Radius: the radius of the circle that will be used to find the neighbours of a point.
- Cluster Neighbours Points: the number of neighbours that a point must have to be considered a cluster.
You may need to tweak parameters 3 and 4 to get the best results.
Example
This is an example of a tiledmap with collisions. I've created 5 different layers, I want to apply rigidbodies only to the platforms and traps. The other layers are just decorations and I don't want to apply any rigidbody to them.
Tiled layers
├─ Traps
├─ Decorations
├─ Stairs
├─ Platforms
└─ Water
I Cocos Creator I've just added the TiledMap
and the RigidBody
components to the layers I wanted to apply collisions to. Remember to set the rigidbody type to Static
if you use gravity or the layer will fall.
And voilà, as you can see the PolygonCollider
was generated automatically from the tiles of the layer.
TIP
I've found some glitches with the TiledMap when scrolling, some layers were not drawn correctly. I've fixed it by adding a rigidbody to the TiledMap
.
WARNING
TiledMap
can't work on _borders, for instance, if you need to have a frame-like border you need to create 4 different layers and apply the TiledMap
component to each of them. If not Hull.js will consider them as a whole and will generate a single collision shape for the whole border.
┌─────────┐ ──────────
│ │ │ │
│ │ │ │
│ │ => │ │
│ │ │ │
│ │ │ │
└─────────┘ ───────────