A lot of questions that we received during the game jam event of ludum dare 42 were about the physics setup on unity.
The unity physic engine is by default very efficient and very stable, for instance it automatically sleeps any non-active rigidbodies. So, I’m gonna share with you some tips on choosing the right metrics for your physic game and how to optimize it.
Gravity setting is very important, it can drastically change the way your game is supposed to be played. Should it be slow and easy? Or should it be quick and responsive?
Example of different gravity parameters for our game:
We tweak the physic time to apply slow motion in the game:
Don’t forget to multiply the fixed timestep as well for the physic.
Mass for every rigid bodies are assigned by their size in the game and by how many game objects are supposed to stand on it.
we also use joints to help our platforms to stay in place and to avoid crumbling before the player can jump on it. Use fixed joints preferably.
This is how our trees are done:
They all have physic joints that keeps them glued together, if the player uses it as a tether with his tongue the tree will wobble, if a large object hits the tree hard it will explode in different parts. The only thing you have to keep in mind is the shape of your physic collider, always convex and parts should never be inside another one, (keep the vertex coplanar).
We had to wrote a script that lists rigidbodies and sleeps them manually (turn their rigidboby into kinematic) until the player reaches them, to avoid excessive compute time at scene load.
Be aware that using a list to store rigidbodies will increase the scene size.
Mesh collider convex
You should always use primitive colliders when you can for performance, sphere colliders are the cheapest one.
However, if you can't, use mesh collider, but if you want to add rigidoby to them you MUST have a mesh collider that is convex. You'll need to divide your meshes into parts of primitive or convex mesh colliders. Some example in Crumble:
The physic for our cannonballs is very important to us for the survival part of the game, it should be able to crumble the platforms it hits but not too much. That's why we decided to make it explode into pieces on impact, it adds feedbacks and doesn't unbalance other platforms too much.
Unlike the trees we don’t need to keep them together with joints, we just activate their physics upon impact.
Another aspect of our game is optimization, we really want this project to be running by most people on their computer.
In every project it is strongly recommended to set the static flag on most of the assets, so that it can batch with other static object and its collider isn't updated every frame. But when you have a lot of dynamic assets you should enable dynamic batching in unity which is not enable by default for some reason.
There are few rules to respect for dynamic batching to work in Unity:
You should have the same material for everything (most of your assets). That means you should have one shader, one material and one texture atlas for everything in the scene, idealistically. So that it doesn't break the batching of frames because you used another material. This is maybe the hardest one because it gets tricky when you need to lerp or animate some shaders like explosion or dissolve. for our explosion we used the vertex color data of the mesh to lerp the B&W texture. Example:
Your mesh should have less than 300 vertices. It sounds like a lot but it's really not, something that many don't know is that "sharp edge" or "flat face" depending on what modelling tool your using means duplicated vertex, example:
So, if you have a mesh with only 250 vertices and every face is flat, you actually have more than 750 vertices which breaks the batching. Our models in Crumble range between 150 and 250 vertices. If you're not making a dynamic physic game like us, you should probably batch everything yourself and have big large static mesh with one material.
Your mesh with its shader shouldn't have more than 900 vertex attributes. That means you will never dynamically batch with your fancy pbr shader that you made.
You can use the frame debugger in unity to debug your batching problems.
It is important for each project to keep working on optimization while working on the production of the game. For instance, you can't switch from DirectX to OpenGL at the end of the development pipeline, you should work with a base of relative optimization, always debug with profiler open to see if any shader or script or physic object compute too much and cut it if you have to. You should be aware of what to use before starting a project, whether it's a physic-oriented game or an isometric story telling game. There isn't any magic button you can press at the end to make everything smooth and stable, although there are some neat tricks that can help such as LOD system, culling after fog, Occlusion culling, frustrum culling, pooling prefab, quality settings etc..