Unity is a multi-platform game development engine used by the majority of game developers. It enables you to create and distribute 2D and 3D games and other graphics applications.
At ARM, we care about game developers. We know we can now achieve console quality games on mobile platforms and we therefore compiled the “ARM Guide for Unity Developers”, a compilation of best practises and optimized techniques to get the most from an ARM mobile platform. Whether you are anything from a beginner to an advanced Unity user, you will find the advice you need to increase the FPS in your graphics app.
Optimization Process
The guide starts by covering the optimization process, so that developers learn the optimal quality settings and the fundamentals of the optimization process. It showcases how to use the Unity Profiler and Debugger as well as the ARM developer tools (Mali™ Graphics Debugger and Streamline).
The profiler is used as a first step, to take measurements of the graphics application and analyze the data to locate any code bottlenecks. Then, we determine the relevant optimization to apply, and finally the developer needs to verify that the optimization works.
The guide dedicates a whole sub-chapter to another very useful ARM tool for Unity developers; the Mali Offline Shader Compiler, which enables developers to compile vertex, fragment and compute shaders into a binary form. Also, it provides information about the number of cycles the shaders are required to execute in each pipeline of the Mali GPU, so that developers can analyze and optimize for ARM Mali GPUs.
Optimizations
The optimizations chapter includes everything from ARM Cortex application processor optimizations with code snippets and settings examples, to ARM Mali GPU optimizations as well as asset optimizations.
The ARM Mali GPU optimization techniques include:
- The use of static batching, a common optimization technique that reduces the number of draw calls therefore reducing the application processor utilization.
- The use of 4 x MSAA, ARM Mali GPUs can implement 4x multi-sample anti-aliasing (MSAA) with very low computational overhead.
LOD group settings
- Level of Detail (LOD), a technique where the Unity engine renders different meshes for the same object depending on the distance from the camera.
- The use of lightmaps and light probes. Lightmaps pre-compute the lighting calculations and bake them into a texture called a lightmap. This means developers lose the flexibility of a fully dynamically lit environment, but they do get very high quality images without impacting performance. On the other hand, the use of light probes enables developers to add some dynamic lighting to light-mapped scenes. The more probes there are, the more accurate the lighting is.
- ASTC Texture Compression is the most efficient and flexible texture compression format available for Unity developers. It provides high quality, low bitrate and many control options, which are explained in detail.
- Mipmapping technique to enhance visual quality as well as the performance of the graphics application. Mipmaps are pre-calculated versions of a texture at different sizes. Each texture generated is called a level and it is half as wide and half as high as the preceding one. Unity can automatically generate the complete set of levels from the 1st level at the original size down to a 1x1 pixel version.
- Skypboxes as a means to draw the background of the camera using a single cubemap, requiring only a single cubemap texture and one draw call.
- How to implement efficient real-time shadows in Unity. Unity supports transform feedback for calculating real-time shadows and for advanced developers the guide shows how to implement custom shadows based on a very efficient technique using local cubemaps in the “Advanced Graphics Techniques” chapter.
- Occlusion Culling consists of not rendering the objects when they are not in line of view from the camera, thereby saving GPU processing power.
- How to efficiently use OnBecameVisible() and OnBecomeInvisible() callbacks
- Rendering Order is very important for performance. The most optimal way is to render opaque objects front-to-back, helping reducing overdraw. Developers can learn what latest hardware techniques are also available to reduce overdraw, like early-Z and Pixel Forward Kill (PFK), as well as what the options provided by the Unity engine.
Developers can optimize their application further by using asset optimizations and a whole sub-chapter addresses this, covering how to most effectively prepare textures and texture atlases, meshes and animations.
Enlighten
The Unity engine supports Global Illumination (GI) using Enlighten from v5 onwards. Enlighten is the ARM Geomerics real-time GI solution.
Enlighten in Unity can be used for baking light maps, light probes and for real-time, indirect lighting. The Enlighten components are not explicitly exposed in Unity, but they are referenced in the user interface and the guide therefore also explains what they are and how they work together.
The Enlighten section also explains how to configure Enlighten in custom shaders, the code flow and what developers need to do to set up Enlighten in the vertex and fragment shader code. It showcases a version of the Unity Standard Shader that is modified to include directional global illumination.
Enlighten Lightmap Images: above left - Ice Cave demo, above right –
its UV Chart lightmap, below left – its Irradiance lightmap, below right – its directionality lightmap
Advanced Graphics Techniques
Chapter 6, the longest chapter of the guide, explains Advanced Graphics Techniques. These techniques are mainly implemented using “Custom Shaders” as the Unity source code of built-in shaders does not include the majority of advanced effects. The chapter starts by describing how to write and debug custom shaders and then goes on to explain how to implement advanced graphics techniques used in the Ice Cave and Chess Room demos. It also shows source code snippets:
- Reflections with a local cubemap: this technique is implemented in Unity v5 and higher with reflection probes. You can combine these reflections probes with other types of reflections, such as reflections rendered at runtime with your own custom shader.
- Combining static reflections based on local cubemaps with dynamically generated reflections
Combining Different Types of Reflections
- Dynamic soft shadows in a game scene there are moving objects and static environments such as rooms. Using dynamic soft shadows based on the local cubemap technique, developers can use a texture to represent the shadows and the alpha channel to represent the amount of light entering the room.
- Refraction based on local cubemaps – another lighting effect using the highly optimized local cubemap technique. Developers can combine the refractions with reflections at runtime.
- Specular effects using the very efficient Blinn technique. In the example provided from the Ice Cave demo, the alpha channel is used to determine the specular intensity, thus ensuring that the specular effect is applied only to surfaces that are lit.
- Using Early-z to improve performance by removing overdrawn fragments.
- Dirty lens effect– this effect invokes a sense of drama and is often used together with a lens flare effect. This can be implemented in a very light and simple way which is suitable for mobile devices.
- Light shafts - they simulate the effect of crepuscular rays, atmospheric scattering or shadowing. They add depth and realism to a scene. This effect is based on truncated cone geometry and a script that uses the position of the sun to calculate the magnitude of the lower cross-section cone expansion, and the direction and magnitude of the cross-section shift.
- Fog effects– they add atmosphere to a scene. There are two versions of the fog effect: procedural linear fog and particle-based fog.
- Bloom– bloom reproduces the effects that occur in real cameras when taking pictures in a bright environment. This effect is noticeable under intense lighting and the guide demonstrates this effect implemented in a very efficient way by using a simple plane approach.
- Icy wall effect.
- Procedural skybox - to achieve a dynamic time of day effect, the following elements were combined in the Ice Cave demo skybox: a procedurally generated sun, a series of fading skybox background cubemaps that represent the day to night cycle, and a skybox clouds cubemap.
- Fireflies– they are bright flying insects that are used in the Ice Cave demo to add more dynamism and show the benefits of using Enlighten for real-time global illumination.
Mobile Virtual Reality
Last but not least, the last chapter of the guide covers the best coding practises when developing graphics applications for Mobile Virtual Reality.
Unity natively supports some VR devices like the Samsung Gear VR and plug-ins can enable support of other devices like the Google Cardboard. The guide describes how to port a graphics application onto native Unity VR.
Screenshot from a VR application running in Samsung Gear VR developer mode
VR creates a more immersive user experienced compared to running the graphics application from your smartphone or tablet and therefore, camera animations might not feel comfortable for the user in VR. Also, VR can benefit from controllers that connect to the VR device using Bluetooth. Tips and methods to create the ultimate user experience are described in the guide.
A whole sub-chapter is dedicated to how to implement reflections in VR. They can use the same local cubemap technique explained earlier in the Advanced Graphics Techniques chapter. However, the technique must be modified to work with the stereo visual output that a user sees. This chapter therefore explains how to implement stereo reflections as well as combining different types of reflections.
We welcome the feedback on our ARM Guide for Unity Developers, which we keep updating on a regular basis and the document history is on our Mali Developer Center.