
Image via Gearbox Publishing. All other images via author.
The attitude to optimizing games is different for PCs and consoles. Having a well-optimized PC build is always good, but it’s rather a good practice that improves the player’s experience but is not always critical to have. But for console games, the game has to meet the performance criteria to be published. Strict and stable framerate, no long static unresponsive screens, no using all the RAM, saved data size, and read-write operations per minute limitations - getting to console markets requires following this and many more limitations.
In this article, we will discuss the best optimizing practices for console builds, which may also help you improve PC build performance.
Console-specific requirements for game builds
Games on consoles are expected to have a stable framerate, but each game's number may differ depending on game complexity and supported screen resolution, be it 4K, FullHD, or lower.
The most common numbers are 30fps for Gen-8 consoles and Nintendo Switch, 60fps for most games on PS5 and Xbox Series, and sometimes up to 120fps, which is supported by some games on PS5 and Xbox Series consoles. As the hardware is always predefined, it's up to the developer to choose the appropriate resolution and FPS plank to hold and fit in as much quality and content as possible.
Unity development perspective
There are various ways to optimize games. Nadiia Havrylenko, Unity Developer at Pingle Studio, shares our game optimization experience from the Unity engine perspective.
The optimization process is similar for PCs and consoles and consists of two steps: identifying the problem and fixing it.

Risk of Rain 2 screenshot, captured on PS4. Engine: Unity
Risk of Rain 2 screenshot, captured on PS4. Engine: Unity
Unity provides various tools for identifying the problem, such as Profiler, Memory Profiler, and Frame Debugger. When we work on console builds, the toolset depends on the specific console and its devkit. Properly using the devkit functionality provides a deeper look into the problem and a more thorough profiling process, which is extremely useful in occasional cases when universal PC tools fail to work because of platform differences.
Solving the development problems requires much more creativity. Once we identify the issue, fixing it may take more work and sometimes involves quality trade-offs.
Let’s split what we can do to optimize the console game into CPU and GPU parts.
The most common CPU optimization practices involve the following:
Modifying the slowly-performing coed fragments—everyone understands the importance of code quality, but not everyone pays proper attention to it. Rewriting the “slow” pieces of code, moving them to the async thread to run in the background, or caching data to use again later will most likely improve your build's framerate immediately. But note that these actions might also require some additional memory to perform.
Correct memory use—Watching out for memory leaks is another must if you want to improve your game's performance. Identifying and properly fixing these in Unity requires a deep understanding of memory management and knowledge of the structure of each specific project. The widely used Unity tool—Garbage Collector—can overload both CPU and memory, so remember about it even if it’s in the background more. If one frame creates a lot of bytes of garbage, the other will take a lot of milliseconds to clean it up.

Paleo Pines screenshot. Engine: Unity
Paleo Pines screenshot. Engine: Unity
In terms of GPU optimizations, once you detect a frame/scene/point of camera view, rendering which takes a lot of resources, you can do the following:
improve batching;
optimize the involved shaders;
bake more data to avoid calculating it in runtime (which will require more memory);
Transfer some calculations to the CPU (which will take more CPU time).
Extra attention to post-processing is important because most packages are optimized for PCs, not consoles. GPU optimizations are often platform-specific.
Optimization for consoles requires meticulous work, and we usually spend a lot of time on it. Some optimizations will not involve quality trade-offs and can benefit any platform, including the PC build: it can be optimized algorithms that still give the same result (and can be used on PC build), using async or parallel execution approaches, or simple oversights in settings or hierarchy that were located and fixed, etc. Other optimizations, like lowering texture quality, simplifying post-processing, and adding limits on spawned entities, will slightly alter the picture quality, used memory amount, and CPU load and, in rare cases, put limitations on the gameplay process. In this case, it's reasonable to keep them platform-specific - only for platforms that need it.
Olexandr Makeev, Unity Developer at Pingle Studio, shares some more insights on the topic in the context of Unity.
Different optimizations can help a game run more stable, with fewer hiccups and better framerate.
Each type of issue requires specific actions, but the approach to solving them is pretty much the same in Unity. Your best friend, in this case, is Unity Profiler.
The profiler helps to diagnose the root cause of the game's performance issues. Using profiler together with deep profiling allows you to see memory allocations, processing time spent and all of this is tied to specific functions your code is performing. That is the best way to start dealing with performance problems. Profilers consist of different tools, but the most important ones for optimization are the profiler window and memory profiler.
Speaking of the specific issues, here are the most common problems and how to solve them:
Long hiccups and freezes - you can detect them by seeing big spikes in profiler graphs. One of the most common things that causes freezes and hiccups is the Garbage Collector running its routine, creating too many things in one frame, and processing very costly algorithms synchronously. To fix this, search for functions that generate a lot of garbage allocations in the profiler and optimize them to not leave behind any unused objects if possible. In general, try to refactor your code to have a smaller memory footprint;
Demanding/time-consuming functions—There are always some functions you can’t get rid of, and they just require time for processing. Consider moving them to asynchronous execution or at least spreading their load over multiple frames via Corutines;
Running out of memory – It is a common issue for console titles as the memory available is much smaller than PCs. This issue is the main cause of crashes. Use a Memory Profiler to see what objects are taking up all the space and what objects are getting left behind unused. Very often, textures can be left behind as they have native and managed portions pointing at each other, which does not allow the texture to be collected by GC. Hint: Always name the textures you create! Also, leaving behind full arrays/lists of objects you will not use later or creating new arrays/lists instead of reusing the old ones leads to memory leaks;
Long loading time – this is often caused by the game doing work that does not necessarily need to be done right now. Sometimes, it is possible to postpone some things loading if they are offscreen or not even close to the player; they can be loaded later during gameplay. Also, all the things mentioned above apply to loading, too. It can be slowed due to immense garbage generation where GC is forced to run multiple times per frame to clean up all the mess left behind by the loading process. Optimizing your generation/loading functions to take less processing time using Profiler will also help.
And where are some more GPU and CPU-specific recommendations.
It is essential to understand the bottleneck in your game. Depending on whether it is a CPU or GPU you should consider different actions.
For CPU optimizations, you should reduce the constant load in any update functions. Reducing function processing time by just a little may lead to significant improvements as it gets called thousands of times per frame. You can apply everything mentioned above to reduce processing time and garbage generation.
For the GPU optimizations, consider using Levels Of Detail - a system that shows a less detailed version of mesh depending on the area that this mesh is taking on screen. Also, a significant boost can be provided by applying dynamic resolution scaling, which will allow it to smooth out any big performance load moments in the game where there are a lot of objects and effects on the screen.
The drop in resolution at this moment is usually not that evident, especially when combined with any fast upscaling method, but it helps keep a stable framerate. If you have heavy physics computations visible in the profiler, consider optimizing that part, such as using less costly physics methods, using them less often, and using physics layering.
Most importantly, optimizing the game might not be required if it runs at the desired performance level.
Unreal Engine development perspective
Kostyantyn Oleschenko, the Project Lead of the Unreal Engine Development Department at Pingle Studio, shares some insight on the article’s agenda from the perspective of working with UE games.

THE FINALS screenshot. Engine: Unreal Engine 5
THE FINALS screenshot. Engine: Unreal Engine 5
No matter the platform or engine you target for your game, the general optimizing challenges remain the same—identifying the issues and fixing them—but with consideration of Unreal Engine’s specifics.
One of the first things we recommend paying attention to is the rendering type - forward or deferred render. Choosing the most appropriate render type for your exact game is the first step toward optimal performance for any Unreal Engine project.
The next thing we recommend considering is platform limitations. This is typical for consoles, but optimizing your PC build to meet these limitations might help your game cover a much wider range of PC configurations. The most common limitations are: