This tutorial provides some tips n tricks for how to optimize your Unity environments to run well on low end system / mobile systems.
While primarily directed at low - end systems, these tips and tricks will also make a significant performance improvements on your desktop scenes.
When used on some old integrated graphics based machines we were able to increase the frame rate from 2 fps to about 70fps in just a few minutes, and with more time and focus and following all of the tips shared here, I could have done even better.
Unfortunately there is no silver bullet to optimization as every game is different, so the approach I take is to experiment with one setting at at time and keep experimenting and profiling until I get the settings I am happy with. Also, when running in the editor you pollute your settings with editor overhead so the best way to profile is on a properly built project. Be sure you disable vsync to stop it from influencing your profile.
Here are some tips to explore. Some are mobile specific and some are more general. Pick and choose whats good for you:
- Use the terrain settings attached to the bottom of this post for low end systems - this will make an immediate difference.
- Drop the size on your textures and normal maps to be more low end friendly. Experiment with 256 and 512 sized textures. The textures supplied with Gaia are located in Gaia / 3rd Party Samplers / GameTexturesDotCom. You are often better to pre-optimize your textures than to get Unity to do it for you. They will most likely be cleaner.
- Use a maximum of 4 textures on your terrain. Every multiple of 4 textures causes the unity terrain shader to render an additional pass. So even adding 1 texture over the boundary of 4 will cause another pass.
- Run a smooth or two on your terrain after you have finished stamping. Smoothing the terrain reduces the number of polys that need to be rendered.
- Either lose grass completely, or use it sparingly. It is a performance hog. In particular it will cause jitter issues when it is culled. You can shrink the detail distance in your terrain settings, and also lessen the detail density. Make sure that you colour your grass so that it blends with the colour of the terrain - this way you lessen the visual impact of hitting the detail distance.
- By default the camera will use frustrum culling to remove objects that are out of view on either side of the current camera view, however you can get another level of performance as well by also using occlusion culling. Occlusion culling will stop objects that are behind other objects from rendering and will result in more objects being culled than just frustrum culling. Rendering less objects results means less draw calls and higher performance.
- Reduce your shadow distance for each of the quality settings you use. If you can get away with it, use hard shadows. You will find these under Edit -> Project Settings -> Quality : Shadow Distance. Also explore the other shadow settings while you are there. Click on Game view and experiment to get the visual settings you want.
- Reduce your LOD bias for each quality setting you support. You will find these under Edit -> Project Settings -> Quality : Lod Bias. Click on Game view and experiment to get the visual settings you want.
- Use Graphical Post FX sparingly. Profile the FX to validate their impact on performance. In later versions of Unity you can see these at design time. Click on Game view and experiment to get the visual settings you want.
- Use mobile optimized trees. The tree samples provided with Gaia are desktop trees. If using SpeedTree, experiment with your LOD and wind settings. Preferably lose wind completely.
- Use mobile optimized assets in general. The assets that come with Gaia are good for desktop, but not so great for mobile. Gaia will happily work with whatever assets you throw at it, so you can easily swap your own in.
- Lose wind completely - delete the Wind Zone object that Gaia creates. You will find it under Gaia Environment / Wind Zone in the scene hierarchy.
- Lose Unity water completely. The default Unity water is very inefficient. If you must use Unity water then swap it out for the WaterBasicDaytime version that comes in Standard Assets / Environment / Water Basic. Better yet purchase a good quality 3rd party water shader optimized for mobile such as AQUAS.
- Make sure you mark rocks and other assets that wont move as static, this will allow unity to batch them, which in turn reduces draw calls and increases frame rate. Make sure when you spawn these assets that their scale is a whole number and this will allow Unity to choose the best case between dynamic and static batching.
- In your lighting tab, select either Precomputed Realtime GI, or Baked GI, but not both. You will need to update the lights in your scene to reflect the settings you have chosen.
- In your lighting tab, make your ambient light source a fixed color. This is less intensive than using the skybox.
- In your lighting tab, make your sky a non procedural skybox instead of the default procedural skybox. Its much cheaper.
- Use baked your lighting. The means you lose the benefit of time of day lighting, but you get it back in performance. If you remove shadows and other lighting calculations then this reduces the amount of work the device has to do.
- Lighting tip : Often in editor mode you will have objects that look really dark. Usually they will display correctly only after you have finished the lighting bake. Be sure to set objects that don't move to static so that they will be affected correctly by lighting.
- Use Forward instead of Deferred rendering path. This is cheaper for environments that have a single light e.g. the sun. It will perform words however if there are multiple lights in the scene. You will find this setting under Player Settings. File -> Build Settings -> Player Settings. Check out the comparison in the Unity documentation here.
- Select the "Fastest" setting under Quality settings. Edit -> Project Settings -> Quality. Alternatively you can also attach the FrameRateManager script in the Gaia / Scripts / ValueAdds directory to a static game object such as the terrain and it will dynamically change your environmental settings to try and maintain a given frame rate. You will need to modify its settings in the script to suit the type of game and the device you are supporting.
- If you do need large environments, use World Streamer. It breaks the terrains down into smaller chunks, and culls terrains that are not in view. It can make a dramatic performance difference even on desktop games.
- In your scripts, never leave the Update method if the script does nothing - this chews up cpu even if its empty. If you must do something regularly, then consider using co-routines, or using a master manager component.
- In your scripts, always cache transforms and components, its much cheaper than getting them during Update.
- In your scripts, never use methods like Find(), except perhaps in Start(), its very expensive.
- In your scripts, avoid using Vector3.Distance(), use Vector3.sqrMagnitude instead.
- In your scripts, avoid using Ray casting, and if you must use, then use sparingly.
- When using colliders, in order of cheapest to most expensive, use Sphere, Capsule, Cube, Mesh, Convex Mesh. Mesh colliders are way more expensive, so estimate the collision volume with a sphere or capsule if you can.
- Use GPU Instancing on your SpeedTree's. Check this post on how to set it up!
Low end terrain settings:
Here is a sample setup for Gaia terrain settings for a low end desktop or mobile. Even if not using Gaia, these settings can be set directly in your terrain object, and will still help your frame rate.
You can download a copy of it here to add to your project. Put it into your Gaia / Data directory. Then open up Gaia Manager and drag it onto the Defaults setting. Gaia will then use these defaults when it creates new terrains.
Note: By dropping values, as suggested here, you are also dropping the accuracy of how Unity will place your textures and grasses, as well as dropping the visual fidelity of the end result. You will need to experiment with these to balance visual fidelity against the frame rate you get on your device. Be aware also that the mobile industry is advancing at a very rapid pace, so you need to make these decisions against where you think the hardware market will be by the time you are ready to launch.
For a more thorough exploration of game optimization in Unity I recommend having a read of an excellent book called Unity 5 Game Optimisation.
Also check these articles at Unity web site:
Check out Gaia:
- Check out Gaia on the asset store.