Mobile optimization presents a number of interesting challenges due to the diverse nature of mobile devices. Mobile devices range from high-end tablets and phones done to lower-end and poorer performing devices where the hardware varies and changes from model to model and year to year.
When developing and building games, it's important to ensure the game will be playable across as many devices as possible. However, developing on desktop and testing on a local device such as a high-end smart phone, may give you a false sense of security, with the end result being confusing negative reviews from your users due to performance, load, lag and other issues. For most independent game developers, it's often not feasible or even possible to test on a wide range of devices. And while emulators do exist, they don't necessarily give a true representation of expected performance.
So why is it so difficult to optimize for mobile games? The immense pressure put on the devices to calculate and redraw every frame to your device's screen, all the while responding to gamer feedback. Fortunately, Unreal Engine provides you with some great tools to help ensure you're going to be just fine.
Let's explore some basic concepts.
Why is it that materials/images/textures are extremely resource hungry? This is due to the way these images are loaded, used and stored.
Assuming a black and white 8bit image you are looking at a value for each and every pixel. For a 10x10 image you have a hundred pixels each with a value from 0-255. This is only in greyscale! To add color – you would make a multi dimensional array adding one 2d array or matrix for red blue and green.
Think of it layering 3 images together to create a single color image. This is one of the ways you can represent a color image. Now for our original 10x10 image we’re looking at 3 times 100 (300) pixels to represent the same image in color. Each pixel with a value from 0-255. As you can see this becomes resource hungry very quickly. Up this to higher dimensioned images – HD – 4k and with or without higher color resolution and you will be quickily eating up all your precious cpu and ram rendering images.
So how does this tie into unreal and other engines? Well they have to store this data and redraw, move, and adjust this images on every frame! Now we’ve taken our huge image matrix and now we will have to redraw it every frame, additionally we may have to perform calculations on it. From llighting, movement, blur, and other affects.
To truly understand the issues materials and images pose on their own you must understand big O notation.
Big O Notation
This simply means that this function or algorithim will perform at the same rate or time regardless of the data size. An example would be to check if the first element of an array is equal to zero
Think of a binary search, where your finding something based on some values. Such as finding your name in a phone book.
This algorithim will continue to the end of the dataset. Meaning it will grow linearly with the data set.
This is related to the squre of the size of the data set. Meaning the bigger the data the harder and longer it will be to compute. These algorithims are usually during nested problems or such as 2D arrays – such as images and Textures!
These grow dramatically! An example is the fibanacci sequence.
How does Big O Apply to Images
Okay so now we have an understanding of the computational complexity for datasets. Now think of an image/material as a dataset. This dataset is already massive due to the nature of color images. Now for every single pixel in the image we need to add the affect of shadows, blurs, and lighting.
For each image we will need to perform a ‘convolution’ to determine the new output dataset. Without getting to much into image processing the game engine will do these calculations in real time. The complexity of these convolutions are usually around O(n^2).
Now not only are you rendering the image every frame you are computing and iterating through the image possibly twice, calculating and manipulating the image on each frame. This can add up extremely fast and hence why materials are so critical to game performance.
The Ultimate goal of Unreal Editor Settings is maximize the performance whilst still keeping the game and its components looking good on as many target platforms possible.
Unreal Editor Settings and Tools
This is built in engine tool that helps to track down performance of the game either live or captured. Its under Window > Developer Tools > Session Frontend.
In Session Frontend, select the Profiler tab. In Profiler window, to see the data collected during the game, slelect Data Preview and Live Preview. To start capturing the data select Data Capturing option.
Profiler can used to track down every call to each method and every action taken in the game. You can check and go through each part of your game and track all potential actions or methods that decrease you frame rate.
For detailed information on Profiler, follow Epic's documentation.
In order to identify the GPU cost for various passes, ProfileGPU Command is very helpful. You can either use the UI based or text base version. Ensure the overall cost of each frame is optimized by looking at components like Materials, dense triangle meshes, far view distance add to the cost.
In order to access GPU Visualizer enter ProfileGPU command in developer console. Once started, it shows the time of each rendering pass within the snapshot and a rough idea of where in the scene those passes took place.
For more details on using this tool follow Epic's documentation.
Forward Rendered or Deferred Rendered
Forward Rendered is the default option in Unreal Engine, which make everything looks great. But for end platforms like VR or other low end platforms, this might end up decreasing the performance of the game. Not only is Forward Rendering faster, it also provides better anti-aliasing options than the Deferred Renderer, which may lead to better visuals.
In order to enable Forward Renderer go to Edit -> Project Settings. Under Rendering option check the Forward Shading option. You might need to restart the editor in order to apply the changes to the project.
As forward Rendered option leads to some loss in quality of reflections, lighting, and shadows, but remainder of the visual effects remain unchanged. However this simple change can have a large impact on the performance of your game.
For more information about about Forward Renderer follow Epic documentation.
LOD (Level of Detail)
A 3D model can have thousands or hundreds of thousands of triangles or vertices. However when a player is far from the model the player won't be able to see the details of the model, therefore, fully rendering the model has no distinguishable affect. When the player further away you load the lower poly models and increase it when the player is closer. This can be controlled by using LOD option that will end up showing more detailed model when up close and less detailed model at a distance.
LODs are created at the creation of the 3D model. Nevertheless, Unreal Engine provide us with a great tool to auto create LODs.
To auto generate Static Mesh LODs, go into that model’s details tab. On the LOD Settings panel select the Number of LODs you would like to have. By generating as many as 5 LODs can have significant improvement in GPU performance.
We can also control the material of each LOD separately, which is another major improvement, thus another reduction in rendering our Static Mesh.
For more details follow Epic's documentation.
Instanced Static Mesh
Every time an object is used in the scene, graphics hardware is loaded with draw calls. If you have hundred of the same static meshes drawn over and over again thats a huge load on the GPU. This can be lowered by instancing the Static Mesh if used repeatedly in the scene. This will reduce the time to draw cells hence a very important but simple optimization.
It's important to note that in an Instance Static Mesh if any single part of the mesh is rendered the whole mesh collection will be rendered. This is clearly not optimal if the entire collection is not visible. Think about a collection that contains 100 spheres. If all of them are in the scene (zoomed out view), then using the Instance Static Meshes is a great solution, but if not all of them are in the scene (zoomed in view), then again entire collection is rendered even if the player only sees a subset of the collection.
This is concept of not rendering the parts which are not visible to the player. This improves the performance of the game as not everything needs to be rendered. To see the occluded objects with their green bounding boxes, you can enter r.VisualizeOccludedPrimitives 1 (0 to turn off) into the console command of the editor.
The controlling factor here is the bounding box of the object, which determine if the object needs to be rendered or not. If the bounding box is visible to the player the object will be rendered. Size of these bounding boxes can be controlled under Static Mesh Settings. The bounding box size can very handy when an object needs to be rendered before it's position is visible to the player. This can be achieved by increasing the size of the bounding box which will result in rendering of the object ahead of time.
Occlusion is very powerful feature offered by Unreal Engine. But using this feature efficiently can be little tricky. Think about a scene in which the player standing in hall. Hall is very detailed and rendering this is heavy for the GPU. Improving the performance of the game using Occlusion depends on how this room model was made(built). If it is a single large model, then as soon as player sees one part of the room, the entire room will be rendered, which is not very efficient. To improve this, the room needs to be built in small pieces, which will allow the game engine to use occlusion effectively.
These are some, but important settings that you can tweak in your game that can improve the performance of your game. The key in using above or similar settings is to keep the frame rate as high as possible without compromising with the quality and performance of the game. However, these settings and ideas are just the tip of the iceberg when it comes to mobile optimization and should serve as a good starting point.
Latest Buzz Words