One of the most ambitious aspects of Core Strand's Encircled is the sheer number of enemies, projectiles and particle effects that can be on screen simultaneously - all while maintaining a crisp frame rate. Here are some fairly easy to implement (but just as easy to overlook!) tips for achieving that kind of performance on mobile VR devices.
Optimize every step of the way - not just at the end
This is more general advice than a specific tip, but it's worth keeping in mind. No matter how small you believe your game is, it's huge. However big you think it is, I promise it's bigger. That's even without things like scope creep. Instead of getting to the end and finding out that your game is a poorly optimized mess (with little to no idea as to what could be the primary culprits), test and improve constantly. If something is having an outsized effect on performance, address it immediately. Nothing is worse than thinking you're almost done with a project, only to find out your work has just begun (and that a good deal of it might have to be sacrificed in order to hit your performance targets). Along with this, I’d highly recommend determining your performance goals early on and then aiming to exceed them!
Cut sprites, not corners
It can be tempting to haphazardly throw artwork into the game, get excited about how great things suddenly look, and forget that the art on display does not come cheap. There are many techniques artists employ to make their work "game-ready," but it's just as important to make sure we use that artwork efficiently. For VR in particular, it's crucial to reduce Batches, Set Pass Calls, Draw Calls, and to minimize Overdraw.
If that last sentence totally made sense to you, feel free to move on! If it sounded like gibberish (or you understood it conceptually but aren't sure what to do with it on a practical level) then the rest of this is for you.
Batching, Set Pass Calls, and Draw Calls
Batching: This process involves grouping similar objects together so that they can be rendered in a single draw call, reducing the overhead on the CPU and GPU. For mobile VR, where processing power is limited, effective batching can significantly improve performance.
Set Pass Calls: These are essentially the number of times the GPU needs to switch between different rendering settings. Reducing these switches, by organizing and minimizing material and shader changes, can help maintain high frame rates.
Draw Calls: Each draw call is a request to the GPU to render (draw) objects. Too many draw calls can overwhelm the GPU, leading to frame rate drops. Optimizing the number of draw calls by combining objects, reducing materials, or using more efficient shaders is crucial.
Static Objects Optimization
For objects in your VR environment that don’t move, these are considered static and should ideally be treated as such by your engine of choice. In Unity, for instance, you can mark an object as static with a checkbox. Doing so a llows the engine to optimize these objects more aggressively, such as by combining them into fewer batches or optimizing their rendering path.
Shader Simplification
Not everything needs to use the most complex shader available. For several levels in Encircled, background objects are not interacting with lighting whatsoever. Using the simplest shader available, sometimes an object’s material can simply have its material’s color adjusted to give the impression it is being affected by lighting, while sparing the GPU from a solid chunk of extra work.
Lighting Baking
Dynamic lighting is costly, especially in VR. Baking your lighting for static scenes or objects can significantly reduce the runtime computational cost, as the lighting calculations are pre-computed and stored. This not only frees up resources but also can improve visual fidelity without compromising performance.
Mesh Combining
When possible, combine multiple meshes into a single mesh. This reduces the number of draw calls and can improve batching efficiency. However, be cautious with how much you combine, as overly large meshes can also have a negative impact, especially on memory usage and loading times.
Material and Texture Minimization
Reducing the number of materials and textures in your game reduces the complexity of rendering operations. Try to use atlases where possible, which combine several textures into one, to decrease the number of texture bindings the GPU has to perform. Simplifying and sharing materials across objects can also reduce set pass calls.
Overdraw Minimization
Overdraw occurs when the same pixel is drawn multiple times within a single frame. This is often costly and unnecessary, particularly with transparent or semi-transparent materials. The first time Encircled had Spirit Channeling up and running, the particle systems cut the frame rate in half. Too many semi-transparent materials were overlapping (like plants or grass being overlapped by a particle system taking up a huge chunk of the screen space). Minimizing overdraw by careful placement of objects, optimizing (even sometimes just scaling down) particle systems, and culling unnecessary rendering can lead to big performance gains.
More specific advice on how to implement these optimizations may vary depending on what game engine you decide to use. The important thing is to stay on top of it, and don't be afraid to do a little digging through the documentation of your engine of choice.
Good luck optimizing!
Comments