Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


Adding diagnostics to C# code

Use the managed code variant setting to include additional diagnostics, debug symbols, or instrumentation in your compiled C# code to help with debugging or profiling a built Player.
Read time 4 minutesLast updated 6 days ago

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 Profiler such as profiler markers 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 build 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 profile. 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 scripts 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
ReleaseNone.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