The need for optimization
Introduction
In the assignment II, we have built the scene and growth animation of our trees. For this assignment, we chose to improve the tree generation speed and quality. In the quality part, the last assignment was lacking in properly UV mapping which was added together with the procedural generation of the mesh. In the other hand, the tree mesh generation performance was sub-par, in the sense that it was intended to be real-time, but sometimes it would fall bellow 1 fps (frame per second), while we aimed to be above 30 fps.
After some profiling and analysis we find out that rendering the final number of triangles (~1.6 millions) were not a problem, but generating them in C#. So the main idea was to reduce the triangle count without impacting the overall mesh quality, split the generation work among various threads and avoid generating everything at the same time. While doing so, we found out some constraints imposed by the unity engine design:
- There is no direct access to mesh data (vertices, triangles and uv). Given that, every time we update the mesh we need to copy its data from our local C# script to unity mesh object.
- When using threads to make calculations one can not call any method from unity. This imposes the need of allocating work memory for each object instead of per thread, as one need to calculate everything and after it, setting up unity mesh all together in the main thread.
- Unity manual states that meshes with intensive updates should be marked as dynamic. While updating the meshes we had no gain using it, and after the growth animation had ended we had big losses(about half the fps) using it.
With all those points in mind, we reworked the original script, merged the generation of all trees in the same script instead of running one per tree, implemented the Level of Detail feature to reduce the triangle count, splitted the work among various threads and other minor tweaks to the C# code.