Thursday, April 5, 2018

FPS Tower Defense Toolkit v3.1 Dev Log #3: Performance Optimizations

In the first part of the v3.1 dev log series for FPS Tower Defense Toolkit, I had briefly covered the process of adding support for multiple power cores. While the implementation itself required only minor modifications to the existing systems, it did introduce an additional layer of expensive nav path calculations. This caused a visible dip in performance when using multiple powers cores, and as a result, I had to spend more time focusing on optimizations before releasing the update.

Since the new performance issues arose as a direct result of the additional navmesh updates, it made sense to try and reduce the cost of these operations. While contemplating on what to do in that regard, I remembered an old Unreal Engine live stream session with Mieszko, in which he talked about the various recast navmesh parameters that were exposed to the editor. So I went ahead and checked it out again with the hopes of scavenging something that could be useful in the current scenario. And fortunately, It seems that decreasing the 'Tile Size UU' attribute of the recast nav mesh reduces the amount of nav mesh area that needs to be rebuilt at runtime. Since the tower placement operations essentially modify only a small part of the navmesh at any instant, I reduced the tile size to bring down the number of calculations required. The 'Cell Size' parameter was also increased in order to improve performance at the cost of nav mesh resolution, as was mentioned in the video.

Next up on the list was rendering optimizations. The grid cells used for tower placement were basically planar meshes with a masked grid material applied to them. Since having lots of masked materials across the map can be taxing on the rendering system, I replaced them with a square window frame shaped mesh that uses a basic unlit material.

The next area for cutting costs came in the form of memory optimizations. Static Meshes within Unreal Engine have an attribute 'HasNavigationData' that determines if it is necessary to save collision data for navmesh calculations. But it happens to be the case that most static meshes used within the context of the toolkit do not interfere with the navmesh. Even the tower bases, being one of the few exceptions that impact the underlying nav mesh, use custom nav modifier volumes to create impassable regions. So it made sense to turn it off wherever not required, and thus save memory on collision data.

Now onto the final optimization. While I had some idea about the benefits of all the above three cases, the next one was completely new information to me.

During the tower construction phase before a wave, navigational paths between enemy spawn points and their linked power cores are evaluated in order to ensure that a valid path exists for the AI bots. Since this is a continuous operation, I was looking for ways to make it more efficient. A couple of ideas did cross my mind, but they would require major alterations to the holographic tower display system. Not wanting to delay the update any further unless absolutely necessary, I was searching for other alternatives. And that was when I stumbled upon a thread from the Unreal Engine forums with a potential fix for the issue. As per the instructions posted in the thread, I added the 'Enable Recalculation on Invalidation' node while calculating nav paths and set it's 'Do Recalculation' enum to No. It basically prevents the 'Find Path to Location Synchronously' function from automatically recalculating the path points if the previously calculated path gets invalidated due to changes in the underlying navmesh. And fortunately, coupled with all the other measures, the toolkit was back to its functional state again.

With that, we've reached the end of this dev log. As mentioned earlier, I think there's still room for cost-cutting within the holographic tower display system. But it might require some major changes to the system and hence I'm pushing it onto the next update. Apart from that, there are a couple of bug fixes making it into this update. More details about the same will be posted as part of the v3.1 changelog in the Unreal Engine forum support thread.

As a final note, I'd like to point out that the primary focus of the v3.x series of updates is to bring improvements to the following three facets of the toolkit: the wave spawning systems, AI logic, and visual design. So these areas will keep getting a lot of attention over the course of next few updates. However, the idea of adding support for multiple cores was something that I got from the Unreal Engine community and was not part of the planned features. And I'm really glad to have someone point it out. So if anyone has any feature requests that they think will increase the value of the toolkit, feel free to reach out to me with the same.