In this blog, we will talk about good practices for Performance Optimization and achieving good FPS with limited resources usage. Our Technology of discussion is Unity 3D.
We will talk about some core Topics.
Batching is an Important aspect of the fps optimization in unity 3d like other techniques. Batching is rendering objects that share same material together in reduced or single render pass instead of multiple draw calls or passes .
When objects are rendered in single rendering pass it reduces the amount of CPU time and resource usage, hence resulting in smoother game experience and better game performance on the specific device.
While going more into batching, it is further categorized into some types:
Static Batching as stated deals with static objects. Precisely, the objects which are not supposed to move during the gameplay are to be marked static, so that these objects which are static then batched together and rendered in a single Call, Resulting in lesser CPU time being dedicated for their rendering hence resulting is smoother processing. Basically, static batching works to bind objects that share the same material (having same material) and render them in single pass.
So its always a good practice to keep un moving objects static.Also advisable to use texture atlasing as much as you can(Large Texture containing multiple texture), to keep the amount of materials down and also combine all objects into a mesh which are situated or placed together, And use static batching to benefit performance.
But there is an important point here,
A mistake that mostly developers make, If you are using Occlusion Culling (which will be discussed later) than marking too many objects static may cause more CPU usage, hence causing more CPU Time being dedicated for the culling of objects, thats why it is advisable to be precise with marking objects static, if you are using static batching with Occlusion Culling. Because Occlusion Culling is also another powerful approach for optimization but it comes at the cost of CPU processing.
Another Mistake that mostly developers Make,
When using static batching, sometimes the objects are not batched together, one of the main reasons of the breaking are Baked Lightmaps(Another Powerful Rendering Approach to be discussed). What happens is when you have a scene that is baked with multiple lightmaps, unity finds it difficult to batch objects with different lightmaps. Hence Causing the static batching to break and making multiple render passes. So it is advisable, trying to be careful with using static batching with Baked Lightmaps as well.
It is advisable to use the Frame Debugging, to see the reasons in such case
Yet another exciting prospect of game development for optimization, static batching is only for static objects, Unity deals with the batching of moving objects with dynamic batching. We dont need to mark objects static for bringing them under dynamic batching. Unity automatically batches the moving objects that share same material together. But for using dynamic batching we need to follow some rules on objects to batch.
Only those objects that share same material are batched together which follow given rules
- Objects with under 300 vertices or under 900 vertex attributes
- If shader on your object are using multiple UV channels or Normal Channel than the limit for vertices is 180
- It is advisable to use single alpha channel shader on moving objects that are to be batched. Multiple Alpha channel shaders break the batching
- Objects with irregular Scale like (one of them has positive scale and other negative scale wont be batched) like object 'a' has +1 scale and object 'b' has -1 scale and both share same material wont be batched
- If you have baked lightmaps on the moving objects, than objects should share the same lightmap aswell to batch in other case the batching will not render them in single pass causing batching to break
GPU Instancing is a feature introduced after the batching, it is basically used on both static and non static objects. GPU instancing is rendering multiple copies of same mesh with scale and material variation together in reduced amount of draw calls, like different props etc, causing the objects with same mesh but other variations batch together, GPU instancing is basically a checkbox offered on shader on a mesh. But it is only shown on shaders that support GPU instancing. While writing shaders you need to add extra instancing declarations( to be discussed later) to add GPU instancing to them
Culling is another important component for optimization in unity, it also deals with rendering of objects. But different from batching it is more to deal with the View Frustum of the game and not the materials or mesh.
Culling also has different types, which are discuss
Frustum Culling is the process in which objects that are out of the view frustum (game view) completely removed from rendering process, because rendering them will not benefit. Thats why we only render the objects that are in view. By default it is enable in every engine and is enable in unity aswell and requires no effort to setup to use.
Unlike frustum culling, occlusion culling is more effective, occlusion culling takes an extra step and remove objects even from view frustum which are not visible but are present in view frustum and covered with another mesh being in front of them. It is more effective than frustum culling and requires baking inside unity, the objects which are to be culled with occlusion are to be marked occlusion static.
But Occlusion culling normally has a CPU overhead and also takes some size in your build as it bakes some data. Using irregular occlusion culling may lead to CPU overhead, so in that case it may save you multiple render cycles, but the batching overhead could become an issue.
This can be used with static batching, but marking too many objects static may cause CPU overhead, thats why it is a good yet difficult feature to use.
To use static batching, it is advised to experiment with different combinations of occlusion parameters and amount of static objects and find the most suitable scene setting and also use dynamic batching more often when using occlusion culling to evade the CPU overhead.