Version: Unity 6.6 Beta (6000.6)
Language : English
Debugging and diagnostics
Debug C# code in Unity

Adding diagnostics to C# code

The project build process compiles managed (C#) project code into managed assemblies and packages them into an application that runs on a particular platform and architecture.

Depending on the build context, you might want to build different variants of managed code, with different kinds of code paths or metadata included to help with debugging or profiling.

You can choose to include the following kinds of additional information in your managed code assemblies:

  • Instrumentation: Instrumentation code is included in managed code assemblies when the UNITY_INCLUDE_INSTRUMENTATION scripting symbol is defined. Instrumentation is the general term for extra code inserted around your functional code for the purposes of taking observations and measurements. In the context of a Unity project build, it means code related to the ProfilerA window that helps you to optimize your game. It shows how much time is spent in the various areas of your game. For example, it can report the percentage of time spent rendering, animating, or in your game logic. More info
    See in Glossary
    such as profiler markersPlaced in code to describe a CPU or GPU event that is then displayed in the Unity Profiler window. Added to Unity code by default, or you can use ProfilerMarker API to add your own custom markers. More info
    See in Glossary
    and most calls to the Profiler API. For more information, refer to the Profiler API reference.
  • Assertions: Calls to Unity’s Assertions.Assert API are included in managed code assemblies when the UNITY_ASSERTIONS scripting symbol is defined. When UNITY_ASSERTIONS isn’t defined, the assertion methods are stripped out via the [Conditional("UNITY_ASSERTIONS")] attribute, so they add no runtime cost in shipping builds. For more information, refer to the Assertions.Assert API reference.
  • Safety checks: Safety checks are included in managed code assemblies when the UNITY_ENABLE_CHECKS scripting symbol is defined. Safety checks are optional runtime validation that check for things such as out-of-bounds access to containers, concurrent data writes, and attempts to call main thread only APIs from a background thread.
  • Debug symbols: Debug symbols are included in managed code assemblies when the DEBUG scripting symbol is defined. This code is unoptimized and appropriate for stepping through with a debugger.

This kind of additional information makes it easier to debug and profile a built Player but also increases the build size and impacts performance. You usually add it to a development buildA development build includes debug symbols and enables the Profiler. More info
See in Glossary
and omit it from a final release build shipped to customers.

Configuring managed code variants

You can include the different types of information mentioned previously in managed assemblies by configuring the managed code variant for your build profileA set of customizable configuration settings to use when creating a build for your target platform. More info
See in Glossary
. Managed code variants are predefined configurations of managed code, which include different levels of additional information, and define the relevant scripting symbols.

The lowest-level variant, Release, includes no additional information. Each additional level includes everything from the level below. The highest-level variant, Debug, includes everything.

To change the managed code variant for your project in the Unity Editor:

  1. Go to Edit > Project Settings > Player.
  2. In Other Settings, navigate to the Optimization heading.
  3. Set the Managed Code Variant property to the desired value.

You can also read or set the managed code variant from build scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary
with PlayerSettings.GetManagedCodeVariant and PlayerSettings.SetManagedCodeVariant respectively.

The following table lists the managed code variant options:

Managed Code Variant Scripting symbols defined Description Code optimization
Debug DEBUG, UNITY_ASSERTIONS, UNITY_ENABLE_CHECKS, UNITY_INCLUDE_INSTRUMENTATION, ENABLE_PROFILER Adds debug symbols to the Checked variant. Off
Checked UNITY_ASSERTIONS, UNITY_ENABLE_CHECKS, UNITY_INCLUDE_INSTRUMENTATION, ENABLE_PROFILER Adds safety checks and assertions to the Instrumented variant. On
Instrumented UNITY_INCLUDE_INSTRUMENTATION, ENABLE_PROFILER Adds instrumentation and enables the C# Profiler APIs. On
Release None. Adds no diagnostics or instrumentation. On

Example

For example, the following snippet wraps a Profiler.BeginSample and Profiler.EndSample pair so it only exists when instrumentation is enabled. This is only compiled into your managed assemblies when the managed code variant defines the UNITY_INCLUDE_INSTRUMENTATION scripting symbol:

#if UNITY_INCLUDE_INSTRUMENTATION
    Profiler.BeginSample("MyExpensiveWork");
#endif
    DoExpensiveWork();
#if UNITY_INCLUDE_INSTRUMENTATION
    Profiler.EndSample();
#endif

Code variants and Development Builds

In Unity versions before 6.6, selecting the Development Build option in the Build Profiles window produced a Player build that included the equivalent of the Checked managed code variant. This is no longer the case, and you must configure the Checked variant if you want a build that includes safety checks.

Although for the time being the Development Build option still defines UNITY_ASSERTIONS and UNITY_INCLUDE_INSTRUMENTATION, this is subject to change. It’s best practice to use the managed code variant setting to indicate what you want to include in your managed code.

Important: Selecting the Script Debugging checkbox that appears when you select Development Build is equivalent to selecting the Debug managed code variant and produces the same Player build result.

Additional resources

Debugging and diagnostics
Debug C# code in Unity