# UNITY\_64 and DEVELOPMENT\_BUILD deprecation and Managed Code Variants

**URL:** https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546
**Category:** Profiling Tools
**Tags:** Scripting, CPU-Profiler, Performance, Official, Feedback, 6.6-alpha
**Created:** [May 30, 2026, 2:37am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546 "2026-05-30T02:37:53Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [May 30, 2026, 2:37am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/1 "2026-05-30T02:37:53Z")

</div>

Hi everyone,

In Unity 6.6, we’re deprecating the `UNITY_64` and `DEVELOPMENT_BUILD` scripting symbols and introducing a new Player Setting, **Managed Code Variant** , to take the latter’s job. If you’ve ever guarded code with `#if UNITY_64` or `#if DEVELOPMENT_BUILD`, you’ll need to update it eventually. In this post I’ll explain why these symbols were never as reliable as they looked, what’s replacing them, and how to migrate your code, including a behavior change that affects you even if you’ve never typed either symbol yourself.

## Why we’re doing this

Here’s the uncomfortable truth: **`UNITY_64` and `DEVELOPMENT_BUILD` have never been reliable C# defines.**

Whether a build is 32-bit or 64-bit, and whether it is a development or non-development build, is decided solely by the native engine binary (for example, `UnityPlayer.dll` on Windows or `libunity.so` on Android). Unity compiles your C# **once** when you build your project, but the resulting managed assemblies can then be reused across several different native binaries. A few examples:

- On Android, the 32-bit and 64-bit builds are built from the **same** managed code, compiled once. `UNITY_64` simply loses its meaning.
- With the **Generate Visual Studio Solution** build setting on Windows, you choose development/non-development configurations and x86/x64/Arm64 architectures later, inside Visual Studio. At the point you build your project from Unity, it hasn’t even been decided yet what kind of build(s) you’ll end up with.
- Modders routinely drop the _development_ `UnityPlayer.dll` inside shipped games to attach a profiler/debugger, or to get extra diagnostic information. Same managed code, suddenly a “development” build.

On top of that, `UNITY_64` was simply **never defined** on iOS, Android, UWP, QNX, Embedded Linux (and a few others), so any code relying on it was already broken on more than half of the platforms we support. And `DEVELOPMENT_BUILD` was overloaded: some code used it for extra safety checks, some for profiler instrumentation, and some to (incorrectly) detect a development native binary. One symbol was being asked to mean three different things.

## What’s changing

**1. A new “Managed Code Variant” Player Setting** _(landed in 6000.6.0a5)_

You can find it in **Player Settings -\> Other Settings -\> Managed Code Variant** , right below Managed Stripping Level. It decides which diagnostic symbols get baked into your C#, completely independently of the native binary. There are four levels, and each one is inclusive of the next:

| Variant | Defines | Optimized? |
| --- | --- | --- |
| **Debug** | `DEBUG`, `UNITY_ASSERTIONS`, `UNITY_ENABLE_CHECKS`, `UNITY_INCLUDE_INSTRUMENTATION`, `ENABLE_PROFILER` | No |
| **Checked** | `UNITY_ASSERTIONS`, `UNITY_ENABLE_CHECKS`, `UNITY_INCLUDE_INSTRUMENTATION`, `ENABLE_PROFILER` | Yes |
| **Instrumented** | `UNITY_INCLUDE_INSTRUMENTATION`, `ENABLE_PROFILER` | Yes |
| **Release** | _(none of the above)_ | Yes |

The way to think about it, this splits the old `DEVELOPMENT_BUILD` into two clearer ideas:

- `UNITY_ENABLE_CHECKS` -\> heavyweight safety checks, assertions and validation (the “Checked” bucket).
- `UNITY_INCLUDE_INSTRUMENTATION` -\> lightweight profiling, instrumentation and diagnostic logging (the “Instrumented” bucket).

You can also read and set the variant from build scripts via `PlayerSettings.SetManagedCodeVariant(...)`.

**2. `UNITY_64` and `DEVELOPMENT_BUILD` are now deprecated** _(warnings landed in 6000.6.0a6)_

Using either one in an `#if` or a `[Conditional(...)]` attribute now produces a Roslyn analyzer warning (`UAC0008` for `UNITY_64` and `UAC0009` for `DEVELOPMENT_BUILD`) in the Console and in your IDE. **In 6.6 the symbols still work** , you’ve just got warnings nudging you to migrate. If you compile with warnings-as-errors, though, you’ll need to update the code now.

**3. Coming in Unity 6.8: full removal.** The symbols will stop being emitted and using them will become a **hard compile error** (we’re not dead set on this last step: depending on your feedback, we might reconsider and keep them as warnings even after removing them). Either way, 6.8 is the real deadline, so it’s worth fixing your code during the 6.6/6.7 window while the old and new symbols still coexist.

Documentation:

- [ManagedCodeVariant](https://docs.unity3d.com/6000.6/Documentation/ScriptReference/ManagedCodeVariant.html)
- [Scripting symbol reference](https://docs.unity3d.com/6000.6/Documentation/Manual/scripting-symbol-reference.html)

## This affects you even if you never used these symbols

A lot of Unity’s own packages used `DEVELOPMENT_BUILD` internally, and we’ve moved all of them onto the new variant symbols. So their availability is now controlled by the **Managed Code Variant** , _not_ by the **Development Build** checkbox, and Managed Code Variant **defaults to Release** , which turns all of them off. Affected engine features include:

- **Scriptable Render Pipeline (URP/HDRP/Core):** debug overlays, the Rendering Debugger runtime resources, Render Graph Viewer, render-graph validation, the magenta “incompatible objects” pass, Frame Debugger support, and the Volume panel are now gated by `UNITY_ENABLE_CHECKS` (Debug/Checked). Render Graph profiling samplers, URP’s per-pass `ScriptableRenderPass.profilingSampler`, and HDRP’s dynamic-resolution overlay are gated by `UNITY_INCLUDE_INSTRUMENTATION` (Debug/Checked/Instrumented). Build-time stripping of debug shaders and rendering-debugger resources now follows the variant too, so a non-development **Checked** build keeps them and a **Release** build strips them.
- **Unity Physics:** simulation integrity checks are now compiled in for the Debug/Checked variants (still overridable with `UNITY_PHYSICS_DISABLE_INTEGRITY_CHECKS`).
- **Entities:** Entities Journaling (the data behind the Entities Journaling window) is now compiled in for Debug/Checked/Instrumented variants (still overridable with `DISABLE_ENTITIES_JOURNALING`).
- **Adaptive Performance:** Apple and Android provider logging is now available in Debug/Checked/Instrumented variants.

Packages that ship independently of the Unity editor change the same way on Unity 6.6 and newer:

- **AR Foundation** : provider-returned trackable-change validation and misconfiguration warnings (for example, the warning shown when no reference image library is assigned) are now compiled in Debug/Checked variants.
- **PolySpatial** : assertions and the runtime scene validator are compiled in Debug/Checked variants, while statistics, debug object names, and verbose logging are compiled in Debug/Checked/Instrumented variants.

So if you make a Development Build and leave the variant at the default Release, you’ll be missing diagnostics you used to get for free. To get the old behavior back, set **Managed Code Variant -\> Checked** in Player Settings; Checked turns on both the check and the instrumentation paths. Pick **Debug** instead if you also want `DEBUG` and unoptimized code for stepping through a debugger, or **Instrumented** if you want only informational logging or are trying to profile the builds.

There’s a small upside to the same change, too: non-development _Release_ builds no longer drag in some URP debug-display shader variants they used to, so you may notice slightly smaller builds and lower shader-variant counts.

## How to fix your code

Let’s start with `UNITY_64`. Since the bitness isn’t known when your scripts are compiled, the fix is to stop asking at compile time and check it at runtime instead, with `IntPtr.Size`:

```auto
// Before
#if UNITY_64
    UseWidePointers();
#endif

// After
if (IntPtr.Size == 8)
    UseWidePointers();

```

`DEVELOPMENT_BUILD` takes a little more thought, because it was doing more than one job. The first step is to work out which of its meanings your code actually relied on. If you were gating heavyweight safety checks, validation or assertions, that’s the “Checked” bucket, so use `UNITY_ENABLE_CHECKS`. If you were gating profiler instrumentation or diagnostic logging, that’s the “Instrumented” bucket, so use `UNITY_INCLUDE_INSTRUMENTATION` (or put it on a `[Conditional]` method):

```auto
// Safety checks / assertions / validation:
#if UNITY_ENABLE_CHECKS
    SafetyChecks.Validate(data);
#endif

// Profiler instrumentation / debug logging:
#if UNITY_INCLUDE_INSTRUMENTATION
    Profiler.BeginSample("MyThing");
#endif

// ...or on a method:
[Conditional("UNITY_INCLUDE_INSTRUMENTATION")]
static void LogDiagnostic(string msg) { ... }

```

There’s a third case worth calling out. Sometimes you genuinely want to know, at runtime, whether you’re running in a development build and here the variant symbols are _not_ a substitute. Remember that a non-development builds can still be built with the Checked variant, so a `#if UNITY_ENABLE_CHECKS` block could end up compiling something into a shipping build that you never wanted there (logging that leaks auth tokens is the classic example). For that, reach for the runtime property `Debug.isDebugBuild`:

```auto
// Before
#if DEVELOPMENT_BUILD
    Debug.LogError($"Rejecting connection: {payload}");
#endif

// After
if (Debug.isDebugBuild)
    Debug.LogError($"Rejecting connection: {payload}");

```

Finally, if you were using `BuildOptions.ForceEnableAssertions`, that’s deprecated too: replace it with `PlayerSettings.SetManagedCodeVariant(target, ManagedCodeVariant.Checked)`.

## Package / Asset Store authors

If your code has to compile against Unity versions older than 6.6, the new symbols won’t always exist, so you can’t rely on them unconditionally. The pattern we used across our own packages is to gate on `UNITY_6000_6_OR_NEWER` and fall back to a runtime `Debug.isDebugBuild` check on older versions, keeping the diagnostic body written exactly once:

```auto
#if !UNITY_6000_6_OR_NEWER || UNITY_ENABLE_CHECKS
#if !UNITY_6000_6_OR_NEWER
    if (Debug.isDebugBuild)
#endif
    {
        if (library == null)
            Debug.LogWarning("No library assigned.");
    }
#endif

```

And for `[Conditional]` methods, pick the attribute per version:

```auto
#if UNITY_6000_6_OR_NEWER
[Conditional("UNITY_INCLUDE_INSTRUMENTATION")]
#else
[Conditional("DEVELOPMENT_BUILD")]
#endif
static void LogDiagnostic(...) { ... }

```

## TL;DR

- `UNITY_64` and `DEVELOPMENT_BUILD` are deprecated now (6.6) and will be removed in 6.8.
- Replace `UNITY_64` with a runtime `IntPtr.Size` check.
- Replace `DEVELOPMENT_BUILD` with `UNITY_ENABLE_CHECKS` (checks), `UNITY_INCLUDE_INSTRUMENTATION` (profiling/logging), or `Debug.isDebugBuild` when you really need a runtime development-build test.
- The new Managed Code Variant setting drives all of this, and it defaults to Release so set it to Checked to get development-build-style diagnostics back.

I’m eager to hear your feedback and questions on this!

---

<div class="post-metadata">

### Author: ![meredoth](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/meredoth/32/92819_2.png) [@meredoth](https://discussions.unity.com/u/meredoth)
#### Post date: [May 30, 2026, 1:20pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/2 "2026-05-30T13:20:21Z")

</div>

Someone should add the `official` tag to this.

---

<div class="post-metadata">

### Author: ![AndreaGalet](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/andreagalet/32/883621_2.png) [@AndreaGalet](https://discussions.unity.com/u/AndreaGalet)
#### Post date: [May 30, 2026, 1:26pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/3 "2026-05-30T13:26:32Z")

</div>

I really don’t understand how they can add 4 tags but often forget about the most important one 🤦, found this discussion by accident.

---

<div class="post-metadata">

### Author: ![AndreaGalet](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/andreagalet/32/883621_2.png) [@AndreaGalet](https://discussions.unity.com/u/AndreaGalet)
#### Post date: [May 30, 2026, 1:45pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/4 "2026-05-30T13:45:51Z")

</div>

> [@Tautvydas-Zilys](#):
>
> **Development Build** checkbox

There is one thing I don’t fully understand, will we still have the **Development Build** checkbox? is Debug.isDebugBuild linked to that?

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [May 30, 2026, 7:28pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/5 "2026-05-30T19:28:56Z")

</div>

That will be done on Monday, by the community team and also pinned. I didn’t have the permissions to add that one.

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [May 30, 2026, 7:31pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/6 "2026-05-30T19:31:16Z")

</div>

Yes and yes. That isn’t changing, and it will still control which native binary you get (that’s what it always did). Some platforms don’t have that checkbox and instead replace it with a drop down with configs like “debug”/“release”/“master” instead but that’s not new.

---

<div class="post-metadata">

### Author: ![Treyrannosaurus-Rex](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/treyrannosaurus-rex/32/987912_2.png) [@Treyrannosaurus-Rex](https://discussions.unity.com/u/Treyrannosaurus-Rex)
#### Post date: [June 1, 2026, 5:59pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/8 "2026-06-01T17:59:20Z")

</div>



---

<div class="post-metadata">

### Author: ![TheOmnisimush](https://avatars.discourse-cdn.com/v4/letter/t/919ad9/32.png) [@TheOmnisimush](https://discussions.unity.com/u/TheOmnisimush)
#### Post date: [June 8, 2026, 10:44am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/9 "2026-06-08T10:44:46Z")

</div>

Hey, thanks for the explanation of UNITY\_64 and DEVELOPMENT\_BUILD.  
your explanation did clear up why UNITY\_64 was mostlikely “useless” , and for DEVELOPMENT\_BUILD it is more like an “unintended MACRO” that is keep being abused by modders or debuggers.

While I agree that it’s best to remove them, I vote for “keep symbols warning instead of error” even after full removal in Unity6.8.  
The reason is the macro is just too ancient and has been existing and working for years in Unity.  
so this will break and cause problems especially for big projects who’s been developed for years using old Unity and decided to upgrade to new versions,  
or for Developers who are not informed about this.  
( seeing how many likes this post have, I doubt that many people check and know about this information )

so we’ll be thankful if you keep them as warning.  
Again full removal is okay, the macro doesn’t need to do anything once it’s removed, just making it a compile error is what I’m against.

---

<div class="post-metadata">

### Author: ![oscarAbraham](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/oscarabraham/32/84167_2.png) [@oscarAbraham](https://discussions.unity.com/u/oscarAbraham)
#### Post date: [June 8, 2026, 7:34pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/11 "2026-06-08T19:34:43Z")

</div>

> [@Tautvydas-Zilys](#):
>
> The pattern we used across our own packages is to gate on `UNITY_6000_6_OR_NEWER` and fall back to a runtime `Debug.isDebugBuild` check on older versions, keeping the diagnostic body written exactly once

Sometimes I use defines for conditionally doing stuff like implementing interfaces, or overriding interface members with explicit implementations. Sadly, this pattern doesn’t work for those cases.

I’d like to propose that the Roslyn Analyzer should skip warnings for cases where both old and new defines are used. For example, it could allow `#if DEVELOPMENT_BUILD || UNITY_ENABLE_CHECKS`. This would be a much easier pattern to use in packages, less mistake-prone, and it’d support more cases.

---

<div class="post-metadata">

### Author: ![oscarAbraham](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/oscarabraham/32/84167_2.png) [@oscarAbraham](https://discussions.unity.com/u/oscarAbraham)
#### Post date: [June 10, 2026, 4:43am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/13 "2026-06-10T04:43:43Z")

</div>

> [@oscarAbraham](#):
>
> Sometimes I use defines for conditionally doing stuff like implementing interfaces, or overriding interface members with explicit implementations. Sadly, this pattern doesn’t work for those cases.

So I found a workaround in case it helps someone in the future:

`DEBUG` is mostly equivalent to `UNITY_EDITOR || DEVELOPMENT_BUILD` before 6000.6, and it won’t trigger analyzer warnings. One could use something like `#if (!UNITY_EDITOR && DEBUG) || UNITY_ENABLE_CHECKS` to replicate `#if DEVELOPMENT_BUILD` in a way that works across different versions.

All of my actual cases need the conditionally compiled code to run in the Editor. So I’m using `#if UNITY_EDITOR || DEBUG` or `#if UNITY_EDITOR || DEBUG || UNITY_ENABLE_CHECKS`, depending on the kind of code. These directives work across different Unity versions. `UNITY_EDITOR` isn’t really needed because it overlaps with `DEBUG`, but I feel it’s clearer and more future-proof this way.

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [June 16, 2026, 6:57am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/14 "2026-06-16T06:57:59Z")

</div>

> [@TheOmnisimush](#):
>
> While I agree that it’s best to remove them, I vote for “keep symbols warning instead of error” even after full removal in Unity6.8.

Thanks for feedback! I am leaning towards that right now.

> [@oscarAbraham](#):
>
> I’d like to propose that the Roslyn Analyzer should skip warnings for cases where both old and new defines are used. For example, it could allow `#if DEVELOPMENT_BUILD || UNITY_ENABLE_CHECKS`. This would be a much easier pattern to use in packages, less mistake-prone, and it’d support more cases.

The problem is that `DEVELOPMENT_BUILD` is _broken_, even on older versions of Unity where we don’t emit a warning. For your own projects, you might be not using Unity in a way that exposes that, but most packages (including ones that come from the Asset Store) that aim to support multiple versions of Unity don’t really know how the projects that embed them end up using Unity, which will cause it to break, often and silently. The correct way to fix it in older versions is to switch to either runtime checks, or remove the condition altogether. I am hesitant silencing Roslyn warning in those cases as we really want to eliminate the usage of this preprocessor symbol. I do agree that the pattern I showed is not pretty at all, though. `DEBUG` sort of has the same issues in older versions of Unity but in Unity 6.8+ will only be defined for the debug managed code variant. The difference is that it a standard C# define and has a clear meaning outside of Unity, which we will adopt.

---

<div class="post-metadata">

### Author: ![oscarAbraham](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/oscarabraham/32/84167_2.png) [@oscarAbraham](https://discussions.unity.com/u/oscarAbraham)
#### Post date: [June 16, 2026, 8:21am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/15 "2026-06-16T08:21:39Z")

</div>

> [@Tautvydas-Zilys](#):
>
> The problem is that `DEVELOPMENT_BUILD` is _broken_, even on older versions of Unity where we don’t emit a warning.

Even if it’s “broken” in older versions, not only it doesn’t emit warnings: Those directives are the only way to detect it’s a non-release version in order to do some extra checks or Log some extra warnings. Well, yes, one can use C# conditions in some cases, but it makes code less performant. And sometimes the extra checks require extra fields and data structures that I’d rather remove when they aren’t needed (e.g. a call count to detect infinite circular calls).

Usually, when there’s a breaking change, package developers can easily support multiple versions by using preprocessor directives, but here you’re breaking that mechanism itself. And we can’t even use pragmas to ignore those warnings.

The proposed way to handle it in multiple Unity versions doesn’t work for every case, and it’s very verbose and error-prone. So I thought since `DEVELOPMENT_BUILD` is the only way to do this in those older versions, and it’ll do nothing in future versions, allowing it when it’s used together with the new directives could be good enough. It lets you know that whoever is using the deprecated directives is aware of their peculiarities, and is not using them to detect a particular Player dll.

> [@Tautvydas-Zilys](#):
>
> For your own projects, you might be not using Unity in a way that exposes that, but most packages (including ones that come from the Asset Store) that aim to support multiple versions of Unity don’t really know how the projects that embed them end up using Unity, which will cause it to break, often and silently. The correct way to fix it in older versions is to switch to either runtime checks, or remove the condition altogether. I am hesitant silencing Roslyn warning in those cases as we really want to eliminate the usage of this preprocessor symbol. I do agree that the pattern I showed is not pretty at all, though. `DEBUG` sort of has the same issues in older versions of Unity but in Unity 6.8+ will only be defined for the debug managed code variant. The difference is that it a standard C# define and has a clear meaning outside of Unity, which we will adopt.

I think understand. To be honest, I’ve never taken `DEVELOPMENT_BUILD` to mean “using the development UnityPlayer.dll”. I’ve just understood it kinda like “we’re in a non-released temp build to test something, so do some extra checks and Log some extra warnings”. I don’t think I’ve ever seen someone use it to do things that depend on what kind of Player dll is loaded, though I don’t doubt that happens.

I think I understand the risks you are trying to remove from developers. I just think that allowing old directives when used with new ones wouldn’t be more risky in practice, because it’d indicate devs aren’t using the old directives in a risky way.

That said, the `DEBUG` workaround works well enough for me, so even without allowing that, I’ll be fine. I really appreciate you taking your time to explain your perspective. Thank you 🙂.

---

<div class="post-metadata">

### Author: ![carlos\_uws](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/carlos_uws/32/939830_2.png) [@carlos\_uws](https://discussions.unity.com/u/carlos_uws)
#### Post date: [July 12, 2026, 3:09am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/17 "2026-07-12T03:09:49Z")

</div>

> [@Tautvydas-Zilys](#):
>
> | Variant | Defines | Optimized? |
> | --- | --- | --- |
> | **Debug** | `DEBUG`, `UNITY_ASSERTIONS`, `UNITY_ENABLE_CHECKS`, `UNITY_INCLUDE_INSTRUMENTATION`, `ENABLE_PROFILER` | No |

Can I simply replace the `DEVELOPMENT_BUILD` symbol with the `DEBUG` symbol? Does this also work in older Unity versions?

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [July 12, 2026, 3:32am UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/18 "2026-07-12T03:32:32Z")

</div>

> [@carlos\_uws](#):
>
> Can I simply replace the `DEVELOPMENT_BUILD` symbol with the `DEBUG` symbol? Does this also work in older Unity versions?

That will break down if those checks are there for profiling and you want to use instrumented managed code variant. If you never use instrumented managed code variant, or if you don’t have any profiling related code guarded by it, it should be fine.

---

<div class="post-metadata">

### Author: ![Trisibo](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/trisibo/32/613867_2.png) [@Trisibo](https://discussions.unity.com/u/Trisibo)
#### Post date: [July 21, 2026, 7:53pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/19 "2026-07-21T19:53:21Z")

</div>

> [@Tautvydas-Zilys](#):
>
> There’s a third case worth calling out. Sometimes you genuinely want to know, at runtime, whether you’re running in a development build and here the variant symbols are _not_ a substitute. Remember that a non-development builds can still be built with the Checked variant, so a `#if UNITY_ENABLE_CHECKS` block could end up compiling something into a shipping build that you never wanted there (logging that leaks auth tokens is the classic example). For that, reach for the runtime property `Debug.isDebugBuild`:

Unless I’m missing something, `Debug.isDebugBuild` doesn’t fix that, arguably it makes things worse. If somebody wanted to have code that shouldn’t be leaked in dev builds (let’s ignore for now whether that’s a good idea), they cannot do it now, as now the code will always be there.

And if a third party uses the development version of the native binary, any debug code will be executed, which, in most cases, using `DEVELOPMENT_BUILD` would prevent, even if it’s broken in some cases.

Something that can be quite confusing is that the `DEBUG` symbol means something quite different to `Debug.isDebugBuild`, and you can make builds with any combination of them. I understand there’s no easy fix, but there has to be a way to make things make more sense.

One of my uses for `DEVELOPMENT_BUILD` was to add debugging tools, marks, etc., to development builds without having the code or assets in regular builds (like indicators on correct answers, buttons to execute debug actions, console/hierarchy viewer assets, and things like that). So I guess I would have to use `DEBUG` now, but then they could go unnoticed into non-development builds.

I haven’t given it much thought, and I don’t know what problems it could cause or what can prevent doing it, but why not remove the development build option, and just force non-Release managed code variants to create/use development build native binaries?

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [July 21, 2026, 8:17pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/20 "2026-07-21T20:17:22Z")

</div>

> [@Trisibo](#):
>
> Unless I’m missing something, `Debug.isDebugBuild` doesn’t fix that, arguably it makes things worse. If somebody wanted to have code that shouldn’t be leaked in dev builds (let’s ignore for now whether that’s a good idea), they cannot do it now, as now the code will always be there.

The `DEVELOPMENT_BUILD` define unfortunately gave a false sense of security. It did not prevent such code from going to non-development build in many cases.

> [@Trisibo](#):
>
> And if a third party uses the development version of the native binary, any debug code will be executed, which, in most cases, using `DEVELOPMENT_BUILD` would prevent, even if it’s broken in some cases.

Can you explain this use case a little bit?

> [@Trisibo](#):
>
> One of my uses for `DEVELOPMENT_BUILD` was to add debugging tools, marks, etc., to development builds without having the code or assets in regular builds (like indicators on correct answers, buttons to execute debug actions, console/hierarchy viewer assets, and things like that). So I guess I would have to use `DEBUG` now, but then they could go unnoticed into non-development builds.

To manage additive functionality that isn’t related to diagnostics/profiling, the recommended workflow is to have a separate build profile that enables these things by defining a custom feature define and using that in your code. You can change any kind of things then, including development build, any player setting, scene list, etc, and the only way you’d accidentally ship it is if you built from the wrong build profile.

> [@Trisibo](#):
>
> I haven’t given it much thought, and I don’t know what problems it could cause or what can prevent doing it, but why not remove the development build option, and just force non-Release managed code variants to create/use development build native binaries?

That just reintroduces the problem that separating development builds and managed code variants is solving. I tried explaining it in the original post but the gist of it is that in some scenarios, developmentness is not determined the moment you press build in the editor, and instead can be flipped after the build is done. So Unity editor is unable to force anything like that.

---

<div class="post-metadata">

### Author: ![Trisibo](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/trisibo/32/613867_2.png) [@Trisibo](https://discussions.unity.com/u/Trisibo)
#### Post date: [July 30, 2026, 6:37pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/21 "2026-07-30T18:37:46Z")

</div>

> [@Tautvydas-Zilys](#):
>
> > [@Trisibo](#):
> >
> > Unless I’m missing something, `Debug.isDebugBuild` doesn’t fix that, arguably it makes things worse. If somebody wanted to have code that shouldn’t be leaked in dev builds (let’s ignore for now whether that’s a good idea), they cannot do it now, as now the code will always be there.
> 
> The `DEVELOPMENT_BUILD` define unfortunately gave a false sense of security. It did not prevent such code from going to non-development build in many cases.

`DEVELOPMENT_BUILD` should prevent the code from being compiled in the vast majority of cases, shouldn’t it? Unless I’m missing something, whenever you generate a build with the development build option enabled, that code is gone from the compiled files, no matter if Unity generates the final build or a Visual Studio project. Whether the native libraries end up being the development or non-development ones, it wouldn’t matter for this.

So, unless you did something weird (which you can also do using managed code variants, arguably more easily), I’d say it would be rather difficult to screw up.

In any case, my main issue with the specific quote I commented on is that it seems to imply that `Debug.isDebugBuild` is a substitute for `#if` when you don’t want something leaked, which is not the case (somebody can just drop the development native library in there to get the logs, or just decompile the code).

> [@Tautvydas-Zilys](#):
>
> > [@Trisibo](#):
> >
> > And if a third party uses the development version of the native binary, any debug code will be executed, which, in most cases, using `DEVELOPMENT_BUILD` would prevent, even if it’s broken in some cases.
> 
> Can you explain this use case a little bit?

That comment was just a continuation of the previous paragraph about code leaking, not really any specific use case, other than you wanting code to not execute and not even exist on a build when building with development build enabled.

> [@Tautvydas-Zilys](#):
>
> > [@Trisibo](#):
> >
> > One of my uses for `DEVELOPMENT_BUILD` was to add debugging tools, marks, etc., to development builds without having the code or assets in regular builds (like indicators on correct answers, buttons to execute debug actions, console/hierarchy viewer assets, and things like that). So I guess I would have to use `DEBUG` now, but then they could go unnoticed into non-development builds.
> 
> To manage additive functionality that isn’t related to diagnostics/profiling, the recommended workflow is to have a separate build profile that enables these things by defining a custom feature define and using that in your code. You can change any kind of things then, including development build, any player setting, scene list, etc, and the only way you’d accidentally ship it is if you built from the wrong build profile.

Yes, but it’s more inconvenient in some situations, plus I may want to have those features in a package and not the projects that use it, without having to force the projects to use any specific settings. `DEVELOPMENT_BUILD` provides a built-in standard I can rely on, and now `DEBUG` seems to be more or less the closest alternative.

> [@Tautvydas-Zilys](#):
>
> > [@Trisibo](#):
> >
> > I haven’t given it much thought, and I don’t know what problems it could cause or what can prevent doing it, but why not remove the development build option, and just force non-Release managed code variants to create/use development build native binaries?
> 
> That just reintroduces the problem that separating development builds and managed code variants is solving. I tried explaining it in the original post but the gist of it is that in some scenarios, developmentness is not determined the moment you press build in the editor, and instead can be flipped after the build is done. So Unity editor is unable to force anything like that.

I understand that, “force” was probably not the best word, what I meant was just pairing the development native library with non-release managed code variants when building, even if the developer or player can later change it (hopefully knowing what they are doing). For example, when creating a Visual Studio project, there are already different `UnityPlayer.dll` in `Master` and `Debug`/`Release` (it may be development/non-development versions, or something else).

If you want to give complete control from the build-creation point for users to mix-and-match native and managed versions, then of course there’s no point in doing what I said, it’s just that I don’t understand why you would want to mix-and-match in most cases, to me it seems more confusing and prone to mistakes than helpful, but of course my use cases are not representative of everyone’s.

The thing is, until reading this thread, I always saw the development build option as something that mostly affected the managed code side, adding debug symbols and whatnot, so now I don’t fully understand what it actually does, other than “creates a development native binary, maybe?” and “builds the managed code with `DEVELOPMENT_BUILD`”, but everything else is now a mystery to me… Is there some more in-depth explanation of what happens with the native and managed sides, and how that affects the runtime?

In any case, as a feature request, I’d ask for an option (I’d argue enabled by default) to make non-release managed builds clearly identified at runtime if that’s possible, just like you get a “DEVELOPMENT BUILD” text in the bottom-right corner. I think it really helps prevent actual development builds to be released to the wild, and it should be even more helpful when using managed code variants, as now it wouldn’t matter what native library is used, when testing the build you’d instantly know whether you screwed up or it’s a safe build to release. I will probably add my own implementation of that in my tools, but it would be nice to have it built-in.

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [July 30, 2026, 9:13pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/22 "2026-07-30T21:13:58Z")

</div>

> [@Trisibo](#):
>
> In any case, my main issue with the specific quote I commented on is that it seems to imply that `Debug.isDebugBuild` is a substitute for `#if` when you don’t want something leaked, which is not the case (somebody can just drop the development native library in there to get the logs, or just decompile the code).

The point of that example wasn’t to hide that information from the user: it was to hide it from whoever they send their logs to (maybe to you!) as they may contain private or personal information. If a build is running on their machine, they can always attach a debugger if they want to figure out what values variables hold so that scenario is not particularly useful to protect from. If they swap to a development build binary themselves, they reenable development logging gated behind `Debug.isDebugBuild`, which would be intended in this case.

> [@Trisibo](#):
>
> The thing is, until reading this thread, I always saw the development build option as something that mostly affected the managed code side, adding debug symbols and whatnot, so now I don’t fully understand what it actually does, other than “creates a development native binary, maybe?” and “builds the managed code with `DEVELOPMENT_BUILD`”, but everything else is now a mystery to me… Is there some more in-depth explanation of what happens with the native and managed sides, and how that affects the runtime?

The difference between development and non-development build is which engine binary (on Windows that’s UnityPlayer.dll) is used. These binaries ship precompiled in Unity editor installation directory. You can look in `<UNITY_INSTALL_DIR>\Editor\Data\PlaybackEngines\windowsstandalonesupport\Variations`. This determines a lot of things: whether the profiler exists, whether memory leak detector is enabled, whether certain errors and warnings get surfaced, etc. There are over 1200 places in the engine source code that behave differently based on whether it is a development build binary or not. This is only for native engine source code: both development and non-development builds share the same exact managed engine code DLLs, which we also ship precompiled.

The development build checkbox in the editor does two things:

- For builds where the editor decides which native binary to put in the output folder, it ends up being the definitive choice between whether the resulting build is a development build.
- (For now) it adds DEVELOPMENT\_BUILD define to script compilation. This only affects code and packages in your project - not engine code.

> [@Trisibo](#):
>
> For example, when creating a Visual Studio project, there are already different `UnityPlayer.dll` in `Master` and `Debug`/`Release` (it may be development/non-development versions, or something else).

This is one of the cases where the whole thing was broken: if you checked the development build checkbox, the only thing that the editor build process would do is add that managed define to script compilation. It has no power to choose whether the build ends up being a development build or not: you make that choice in Visual Studio. If you choose Debug or Release configuration, you end up with a development build. If you use Master configuration, you end up with a non-development build (which means you get scripts thinking it’s a development build while it’s not). Thinking about a single development build dimension that affects both native and managed code is incorrect, and was actually causing real serious bugs both internally at Unity, in Unity user projects and Asset Store packages.

> [@Trisibo](#):
>
> In any case, as a feature request, I’d ask for an option (I’d argue enabled by default) to make non-release managed builds clearly identified at runtime if that’s possible, just like you get a “DEVELOPMENT BUILD” text in the bottom-right corner. I think it really helps prevent actual development builds to be released to the wild, and it should be even more helpful when using managed code variants, as now it wouldn’t matter what native library is used, when testing the build you’d instantly know whether you screwed up or it’s a safe build to release. I will probably add my own implementation of that in my tools, but it would be nice to have it built-in.

This is actually a great suggestion! Thanks, I’ll see what we can do there.

---

<div class="post-metadata">

### Author: ![tertle](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/tertle/32/903942_2.png) [@tertle](https://discussions.unity.com/u/tertle)
#### Post date: [August 22, 2026, 9:21pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/24 "2026-08-22T21:21:46Z")

</div>

I’ve been using this for a while and I like the separate instrumental vs checks so i think it’s a good improvement, but i really feel like it needs be a separate option in build profiles that isn’t dependent on with player settings

 ![image](https://europe1.discourse-cdn.com/unity/original/4X/b/1/b/b1be187054dc6f11e02a97f01e14d52a22583f57.png)

having to overload the entire player settings per platform for just this dropdown is super annoying and bug inducing. I’m always going to have at least 2 profiles, 1 for testing 1 for release so I’m always going to need to override this value at least once on a profile and be forced to use a player settings overload.

---

<div class="post-metadata">

### Author: ![Tautvydas-Zilys](https://avatars.discourse-cdn.com/v4/letter/t/4bbf92/32.png) [@Tautvydas-Zilys](https://discussions.unity.com/u/Tautvydas-Zilys)
#### Post date: [September 2, 2026, 10:34pm UTC](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546/25 "2026-09-02T22:34:22Z")

</div>

> [@tertle](#):
>
> having to overload the entire player settings per platform for just this dropdown is super annoying and bug inducing. I’m always going to have at least 2 profiles, 1 for testing 1 for release so I’m always going to need to override this value at least once on a profile and be forced to use a player settings overload.

Thanks for the feedback. I agree with that, overloading whole player settings is a hassle. I’ll see what we can do here.

[Next page](https://discussions.unity.com/t/unity-64-and-development-build-deprecation-and-managed-code-variants/1721546.md?page=2)
