In Fuel Renegades we managed to solve our problem with performance, being it a major inconvenience due to the fact that the game needed to run stable at 60 fps to give a great experience to the user.
What is “instancing”?
Instancing is grouping mesh to draw in a single call instead of telling the graphics card to draw it one by one.
I’ve prepared an scenario in which I’ve placed randomly 5000 cubes. In the first case the cubes are drawn individually and the resulst are lover than 10 fps.
Then I edited the blueprint to work with InstancedStaticMeshComponent and the results are stunning, between 90 and 100 fps.
Why? The graphics cards are prepared to perform parallel actions and drawing 5000 cubes at once is very positive for them.
Okay. Now we have an improvement, how do we apply it to a real problem?
Instancing in Fuel Renegades.
In Fuel Renegades we have tile based everything (buldings, decorations, etc) it lead us to thousands of draw calls. But the level is too complex to go one by one piece instancing manually.
To approach a solution that can be used in every game, I decided to create a tool to convert from a group of StaticMesh to a single InstancedStaticMesh. I’ve named this tool Instancer and that’s how it will be called from now on.
What to instance.
The Instancer looks for all visible objects in the level and takes information out of them.
- Number of materials
This tools has to divide the group of objects into InstancedStaticMesh this is perform by dividing the objects per mesh and them per material, as shown in the image:
This is how the instancer looks like for the user:
With the first boolean you get the visible information out of the scene and with the second one the instances are created.
Tips for working with the Instancer.
The best way to work with assets is individually even though it isn’t how it will be shown in the game using instancing. A good tip for saving a lot of headaches for your artists is to have the assets in a different level from the rest of the game as well of the Instancer.
In this example the indiviual assets are in Art_Assets and the instanced in Art_Game, the others sublevels contains objects that aren’t going to be instanced.
In the load of your level yo can decide no to load Art_Assets and you can enable it to work and that update the Istancer.
Limitations of the Instancer.
This is a great tool but is not valid for some cases, for example the road we created cannot be instanced due to it uses a SplineMeshComponent or any other instanced mesh in the level cannot be reinstaced. In addition, the movable objects aren’t either very friendly to this tool (avoid them to be instanced or create another tool).
One problem found is that if a instance of InstancedStaticMesh get visible, all of the similars will be rendered and thats not so good for Occlusion Culling. A solution can be group per zones.
Instancing is a perfect solution if your game is tile-based in art. The instancer is a powerful tool to optimize your game and easy to use for artists.