Search Unity

How to optimize game performance with Camera usage: Part 1

September 23, 2021 in Games | 8 min. read
Accelerate Success Logo
Accelerate Success Logo
Topics covered
Share

Is this article helpful for you?

Thank you for your feedback!

The world is better with more creators in it, and our new content series, Accelerate Success, is our way of showcasing the technical experience of our Accelerate Solutions Games team.  This team is our professional services group that’s responsible for consulting, co-development, and full development with our customers. They often take on some of the most complex and challenging Unity work where our customers are pushing the boundaries of what Unity can do.

This series, made up of technical eBooks and webinars, is our way of giving back to the greater gaming community that has helped build Unity. The Accelerate Success series will strive to showcase pragmatic and methodological tips and best practices gathered from our experiences working with top studios from around the world. Each piece from the Accelerate Success content series is curated and written by a different Software Development Consultant from our Accelerate Solutions team, and is based on real-life scenarios and findings. 

This blog post series was written by one of our leads on the Accelerate Solutions - Games team, Bertrand Guay-Paquet. Bertrand is based in Unity’s Stockholm office and the findings in this post series come from findings during his Projects Reviews that he has carried out for the team. 

What are Project Reviews?

A big part of the work completed by Unity’s Software Development Consultants on the Accelerate Solutions Games team is to deliver Project Reviews. Project Reviews are annual engagements included with Unity customers who subscribe to our Integrated Success plan. During these engagements, we spend two days onsite (or lately on Zoom) reviewing the client’s project in depth. During Project Reviews, our Software Development Consultant will deep dive into a project or workflows, and deliver a comprehensive report identifying areas where performance could be optimized for greater speed, stability, and efficiency. 

During some of our Project Reviews, we frequently encounter Camera setups that are suboptimal because they have unnecessary Cameras. We normally instantly flag this as something to investigate and our final recommendation to improve performance is usually something along the lines of trying to combine Cameras and removing unnecessary Cameras.

Profiler capture with multiple Cameras - A red flag!
Profiler capture with multiple Cameras - A red flag!

Over the years, we observed that additional Cameras decreased performance in several real-world games. However, until now, we didn’t have a set of benchmarks of different Camera setups in a scene. This eBook will discuss how Camera performance benchmarks on mobile hardware to get a better understanding of the situation. We tested both Unity’s Built-in Render Pipeline and the Universal Render Pipeline.

How to improve game performance with Camera usage: Part 1

What does a Camera actually do?

At a basic level, a Camera defines a field of view, a position, and an orientation in the scene. These parameters establish the content (Renderers) visible by a Camera. The rendered image of a Camera is output either to a display or a RenderTexture. In both cases, the Camera’s viewport rectangle defines the covered output area.

At a high level, every frame, in the Unity engine’s code, each active Camera must:

  • Determine the set of visible Renderers. This is called culling. Culling ensures that only Renderers that potentially contribute to the Camera’s rendered image are drawn on the GPU. In other words, the goal is to avoid drawing as many Renderers as possible to improve performance. Three processes are used for this:
    • Renderers on layers that don’t match the Camera’s culling mask are excluded.
    • Frustum culling excludes Renderers that are outside the Camera’s frustum (i.e. its viewing volume).
    • Occlusion culling excludes Renderers which are completely hidden behind other opaque Renderers. This step is optional and usually not exhaustive.
  • Determine the order in which the GPU draws the visible Renderers. Broadly speaking, the Camera sorts transparent objects from back to front and opaque objects roughly from front to back. Other factors can also affect the rendering order, such as the Render Queue of the material or shader, sorting layers, and sorting order.
  • Generate draw commands for each visible Renderer to submit work to the GPU. These commands set up the Material and Mesh for rendering.

As you can probably imagine, these steps gloss over a ton of details and nuances, but they serve as a good starting point to reason about Cameras.

Camera test scene

To measure the cost of additional Cameras, we used everyone’s favorite test case: spinning cubes! From back to front, every test scene has:

  • A 3D grid of spinning cubes. Each slice is a 10x10 grid of cubes. The number of slices is adjustable and is referred to as the “load factor” in this post series.
  • A single directional light source with soft shadows.
  • 2 “game” UI canvases with a panel each to simulate two popups in a mobile game.
  • A separate “overlay” UI canvas for controlling the test.

The full test project is available on our Accelerate Solutions Games samples GitHub repository.

Single Camera Test Scene
The test scene

We used a configurable number of spinning cubes (the load factor) to simulate different conditions in a game. The first scenario has a low load that should approximate something like a game lobby scene. The second scenario is a high load to simulate more demanding gameplay.

Exploded view of the test scene
Exploded view of the test scene

To get meaningful results, we kept the same scene content identical in all Camera setups. The base scene contains the Main Camera, the spinning cubes, and the UI that controls the test. We then created four scenes containing the “game” UI with different Camera configurations:

  1. The optimal scene with only the Main Camera. The “game” UI canvases are set to “Screen Space - Overlay”.
  2. The 2 “game” UI canvases are set to “Screen Space - Camera” and assigned to a second Camera. This is a relatively common Camera setup we’ve seen used in games.
  3. The 2 “game” UI canvases are set to “Screen Space - Camera” and each is assigned to a separate Camera. This simulates a Camera setup where multiple Cameras are used to composite the UI.
  4. This is the same as the third scene with an extra Camera with its culling mask set to “Nothing” so it doesn’t render anything.

Each test scenario additively loads one of those scenes over the base scene. We used culling masks to ensure that no GameObject is processed by more than one Camera.

Rendering Pipelines

Rendering pipelines are the processes by which a Camera inside a scene produces an image. Unity has a Built-in Render Pipeline which was historically the only option for rendering scenes. Unity 2018.1 introduced the Scriptable Render Pipeline (SRP) which offers many more possibilities to control the rendering from C# scripts. The Universal Render Pipeline (URP) and the High Definition Render Pipeline (HDRP) are the two SRP implementations provided by Unity.

In this post series, we examine the performance overhead of Cameras in the Built-in Render Pipeline and URP because they support mobile devices. HDRP does not run on those devices so it was excluded from this test. A secondary reason for excluding HDRP is that its range of configuration options for render features is quite large which makes it difficult to create fair and meaningful comparison scenarios of inefficient Camera usage.

URP introduced the concept of Camera Stack which consists of a Base Camera and one or more Overlay Cameras. This is what we used for setting up the Cameras in the URP tests. See Manager.cs for the details on how to programmatically set up and change a Camera Stack at runtime.

Test setup

We used Unity 2020.3.11f1 with IL2CPP development builds for our tests. We ran the tests on both the Built-in Render Pipeline and the Universal Render Pipeline. For each render pipeline, we tested with both low and high load factors for a total of 16 profiler captures per device. The five devices used are:

  • Google Nexus 5
  • Samsung Galaxy S7 edge (G935F)
  • Samsung Galaxy A20e
  • iPhone 5s
  • iPhone 7

We used the Profile Analyzer package to get the mean values of profiler markers on the main thread over captures of 300 frames.

A note on mobile performance

Measuring performance reliably is often difficult to achieve since there are both internal and external factors to consider. Mobile phones are notorious for having a few of the latter such as thermal throttling and asymmetric CPU cores. The "Mobile performance handbook: thermal stability" published by our Mobile team is invaluable to overcome these difficulties.

Avoiding thermal throttling with a cooling pack
Avoiding thermal throttling with a cooling pack

This wraps up blog post #1 of How to optimize game performance with Camera usage. Check out our blog in three weeks' time to read about our test results, camera pattern usages to avoid, when to use multiple cameras, and the conclusion of our tests. 

If you can’t wait to read part 2, you can download the full PDF version of the ebook now.

September 23, 2021 in Games | 8 min. read

Is this article helpful for you?

Thank you for your feedback!

Topics covered
Related Posts