Method 1: mega box collider
Use a single BoxCollider for all your planes. For example, if you have multiple aligned planes, remove their Collider component (Box, Mesh, whichever they have) and on only one of the planes, add a BoxCollider and adjust its center and size values in the component’s inspector to encapsulate all the planes.
Pros
- Simple.
Cons
- Supports only rectangular surfaces.
Method 2: generated colliders
If you are rolling your ball on a non rectangular surface, you will need to find a way to generate a mesh collider for all your planes. For this, choose one of the following:
- the hard way: generate the mesh by a custom script: mesh generation starting point,
- the easy way: look for a plugin online or on the Asset Store,
Pros
- Just works.
Cons
- Uses noticeable CPU power when updating (baking) the colliding mesh in real time. Update sparingly.
Method 3: ramps as bridges
Create a set of meshes from a 3D software such as Blender to make invisible ramps which will be placed partly underground between your planes. They have to be large enough to make the transitions as smooth as possible. The height between the top of the bridge and the ground (the planes) should be approximately the value defined by the Default Contact Offset value in the Physics Manager.
Pros
- No real improvement.
Cons
- The ball may jump a little, especially at high speed.
- Doesn’t work with small tiling (or when your successive planes are small): the longer the tiles, the longer bridges can be.
- Requires a lot of testing.
- Requires 3D software usage.
- The result is not consistent.
- Requires good workflow / toolchain.
Method 4: make custom extended planes’ colliders
This one should not work very well.
Create in a 3D software a planar mesh. Then, on its edges, extrude towards outside and lower down slightly the new edges. To put the words into image:
Make them intersect, and hopefully the bouncing will be invisible.
Pros
- Quite simple.
Cons
- The ball may jump a little, especially at high speed.
- Requires a lot of testing.
- Requires 3D software usage.
- The result is not consistent.
- Requires good workflow / toolchain.
Method 5: turn slightly your planes’ colliders
Make your planes’ colliders slightly rotated so that, in the direction of movement, the end of a collider is slightly above the next plane’s collider. The height should be approximately the value defined by the Default Contact Offset value in the Physics Manager and hopefully no bouncing will occur.
Pros
- Works flawlessly.
Cons
- You will see the ball flying and falling a few units from one plane to another.
Method 6: do everything by script
Maybe the Physics is not what is the best for your gameplay. Write your own system with accelerations, collision detection. This is the old-fashioned way and is the choice of a lot of developers! ^^
Pros
- Works flawlessly.
- Permits game design driven gameplay and not by physics.
Cons
- Not using the PhysX forces and gravity.
- Requires to work (omg! 😉 ) to simulate fake physics.
Method 7: Make your ball much larger
By using a greater ball (x10, x100), this could lead to less edge detection.
Pros
- May work.
Cons
- The scale of the simulation would change: if you make everything at the same scale as the ball, objects falling by gravity will look like they fall in slow motion.
- The result is not consistent.
Method 8: collision layers and raycast
This one is pretty cool.
- Keep single BoxColliders for each plane. Set the layer of the plane prefab to SinglePlanes (create the layer).
- Make a big Unity cube with a collider which encapsulates all the planes. Set the layer of the cube to ContinuousPlane.
- Create two layers: OnAPlane and NotOnAPlane.
- Set the ball prefab’s layer to OnAPlane.
- In Physics Manager, set the collision matrix so that:
- NotOnAPlane and ContinuousPlane are not collidable (unchecked),
- OnAPlane and SinglePlanes are not collidable (unchecked).
- On each
Update()
, do a raycast from the center of the ball towardsVector3.down
on the layer SinglePlanes:if(!Physics.Raycast(ball.transform.position, Vector3.down, Mathf.Infinity, singlePlanesLayer)) { // Not on a floor anymore }
- If the raycast returns
false
, the center of the ball is not on a plane. So now, we change the layer of the ball to NotOnAPlane. The ball will start to fall through the hole. - If the raycast returns
true
, set the layer of the ball to OnAPlane.
For how to define a layer, please check the manual.
Pros
- Works efficiently with dynamic floor layout.
- You will learn how to deal with layers and Physics.
Cons
- No real flaws.
Additional Information
- Methods above may be combined.
- You can adjust the physics project settings and / or set the physics materials to reduce the bounciness of your objects.
- Make sure the thickness of the planes collision is not 0f. Make them 1f large or more.
- There is a possibility to reduce the bounces, but I am not recommending it (may cause jittery and physics artifacts): set the Default Contact Offset to 0.0001. Again, I am not recommending it!
- All of this post could be useless when the default PhysX embedded in Unity will be upgraded.
- I originally posted this post as an answer on the Unity Answers website but none of the above methods have been considered as valid by the OP. Hence the removal from the answers website.