What you will get from this page: Tips for setting up your development environment to make games for PlayStation, Microsoft Xbox One, and Nintendo Switch.
Indie teams developing with Unity are behind some of today’s most popular console games. Read on to learn how to set up your development environment, profile and optimize performance, organize and debug your game content, and more. Thanks to Oli Williams, an Xbox One developer at Unity, for the tips.
Register with platform holders
The submission requirements for each console are available as soon as you register. Read them before you start porting your game and keep them in mind throughout production.
For some platforms, you might need a static IP address to be white listed for different services, or register a domain name or a company. Again, check the requirements.
Be aware that Microsoft, Sony, and Nintendo require registered developers to sign non-disclosure agreements, or NDAs.
Set up your development environment
Each version of Unity is compatible with a particular console SDK version. You can download the console SDK from the platform holder once you register. The platform holders upgrade their console SDKs periodically, at which point we upgrade all current Unity versions, including LTS versions, to be compatible with the latest SDKs. However, it’s important to check that your version of Unity is paired with its corresponding SDK version.
Once you register and have downloaded the console SDK, you can begin developing a console game with your current version of Unity. However, we strongly recommend that as you get ready for submission, you move to the relevant LTS branch because it will be the most stable version and include critical bug fixes and SDK upgrades.
Other hardware requirements
You need a Windows 10 PC with Visual Studio installed. Development on Mac Os or Linux is not supported.
The Unity editor provides an extension for each console that tells Unity how to build your scenes and deploy your game to a devkit. If you’ve built mobile games then the workflow will be familiar to you.
Run your project on the console hardware
Running your game in the Unity editor is not the same as running it on the actual console hardware. Your development PC has different specs to each of the consoles and the consoles have different specs from one another. These include clock speeds, save and load times, and the amount of RAM available. In the latter’s case, Nintendo Switch has 4GB, PS4 has 8GB and Xbox One X has 12GB.
We recommend that you run your game frequently on the dev kits throughout development. In particular, test on the lowest available specs: test on the Xbox One instead of Xbox One X, on PS4 instead of PS4 Pro, and on Nintendo Switch handheld mode instead of docked mode. This will help you pinpoint the baseline performance and author your content accordingly.
Profile and optimize performance
There’s a good chance you know this already but just in case, here’s a reminder to always profile content before you optimize it, so you can pinpoint actual performance problems that might require code changes.
If you want your game to run at 60fps then each frame has to be ready to go within a sixtieth of a second, or about 17 milliseconds. If your frames take longer than that you need to discover what you're bound by, i.e. what's pushing that frame time the most. The two most common areas to look at are the CPU and the GPU.
If you're bound by the CPU, it could be due to your script code, disk reads, UI layout rebuilds or even physics. If you're bound by the GPU, you need to pinpoint what part of the graphics pipeline is causing the bottleneck, for example, particles or post-processing effects.
You can profile performance with the profiling tools provided by each platform provider and those built into Unity.
The platform-specific profiling tools allow you to dig into hardware details. You can see what each CPU core is doing at any particular point or how the GPU constructs an individual frame.
Profiling with Unity
Unity’s profiling tools work across all consoles as well as when your game runs on a dev kit. This makes testing and iterating on console builds efficient. For example, you can attach the CPU Profiler directly to your console dev kit and analyze your frames to identify CPU spikes, just as you would in the editor.
You can also see how many garbage collection allocations your scripts make. It’s important to keep track of the allocations because it helps to reduce your memory footprint as well as avoid CPU spikes when the garbage collector runs.
Deep profiling and and profiler markers
Deep profiling combs through each line of code, making it useful for pinpointing hard-to-find allocations. But it’s often slow due to the volume of data that it needs to collect, so use it to profile isolated areas of your code only, such as performance spikes.
An efficient alternative to deep profiling are Custom ProfilerMarkers. Simply place profiler.beginsample and then sample to logically group any part of your script code, typically in suspect areas. You can even nest a ProfilerMarker to get a better idea of what's going on in your game. You just have to make sure that every beginsample has a matching endsample.
Once you do that the sample name you use will appear in the Unity Profiler, allowing you to see the exact timing of that block as well as view any allocation within it. Profiler Markers are compiled out of release builds so you don't need to remove them later on.
Access platform-specific native APIs
Unity provides a set of plugins to interface with platform-specific native APIs directly from your C# scripts. This makes it easy for you to add support for features that are specific to consoles. The plugins come with their own documentation and source code.
For example, every Xbox One gamer is familiar with the popup that appears when they unlock achievements in the game. In order to trigger this popup and control how it’s displayed, you need to call Xbox One- or PS4-specific APIs.
You can do this from your C# script code with the native plugins. You need to get a handle for the current active player and customize the placement of the popup. With one simple call, you can unlock the correct achievement for your player (see code example below).
Additionally, the plugins provide interfaces between certain console features and Unity features. The plugins themselves sit at the boundary of managed C# and native C++ code and come in pairs of native and managed libraries. Simply copy the libraries into your project's plugins folder to use them.
CurrentUser = UsersManager.Users; NotificationManager.SetNotificationPositionHint( UnityPlugin.NotificationPositionHint.BottomRight); AchievementsManager.UpdateAchievementAsync( CurrentUser.Id, Current.UID, “2”, 100, UpdateAchievementCallback);
Organize content and code
Organize game content to ensure small install size and efficient patching
Ask yourself these two questions early on to get a head start on organizing your game content efficiently:
- What features of your game are platform-specific? These can include texture resolution, iconography and native plug-in libraries. With the latter, you’ll want to ship them on the relevant platforms only, to ensure a reasonable install size.
- How will you patch game content? Be prepared to ship bug fixes and additional content to users once your game is live.
Use Unity Addressables to support dynamic game content
Asset Bundles were introduced in Unity 4 as a low-level mechanism for building assets into discrete units for dynamic loading at runtime. Asset Bundles enabled developers to separate content from the app install, so they could deliver regular content updates to live apps with a small initial download size, while staying below the over-the-air install limit as additional app content is added.
However, using Asset Bundles in a real production turned out to be cumbersome for many Unity developers. Therefore, in 2019, we introduced the Addressable Asset System (Addressables for short), which provides an easy way to load assets by “address.” It handles asset management overhead by simplifying content pack creation and deployment.
Addressables use asynchronous loading to support loading from any location with any collection of dependencies. Whether you use direct references, traditional asset bundles,or Resource folders for asset management, Addressables provide a simpler way to make your game more dynamic.
Learn more about Addressables from the manual.
Prepare for limitations: Only Ahead-of-Time compilation works
Developing console games in Unity requires the IL2CPP scripting back end. With IL2CPP your C# script code is compiled into Intermediate Language code (IL) using Microsoft’s .NET Compiler Platform (Roslyn). Next, Unity’s IL2CPP converter translates the IL output into native C++ code which in turn is compiled, using each console platform’s C++ compiler, into a native library that the Player (the executable that runs on the hardware and runs your game) imports and executes. This execution does not use resources to interpret your code at runtime. It's already compiled, ready for the CPU to execute directly, ensuring the best performance.
However, the IL2CPP back end comes with a constraint: you can perform only ahead-of-time (AOT) compilation, as all the code must be compiled and ready at runtime. Certain C# code patterns that rely on just-in-time (JIT) compilation won’t work. Such code patterns are typically found in places that require runtime code generation, such as in the reflection library, and in the special dynamic type. They might also be used in Asset Store packages, so be sure to check with the publisher if a package has been tested on the relevant consoles before downloading it.
This constraint can be a challenge for serialization; however, there are AOT-friendly ways for performing serialization.
For more tips see Oli’s full Unite session on console development.