Upgrade to Unity 6.6
Upgrade a project from Unity 6.5 to Unity 6.6.
Read time 16 minutesLast updated 4 hours ago
This page lists changes in Unity 6.6 (6000.6) in these areas that can affect existing projects when you upgrade from Unity 6.5 (6000.5) to Unity 6.6 (6000.6):
Cameras
This section outlines recent updates to the camera system that can affect your upgrade experience.
Cinemachine 3 is a core package
The package is now a core package and part of the Unity Editor. Any project that depends on this package will automatically upgrade to the version that is part of the Editor.
com.unity.cinemachineIf your project uses Cinemachine 3, this change doesn't affect you. If your project uses Cinemachine 2, Unity automatically updates it to use Cinemachine 3.
Cinemachine 3 is a major version change with a different API and data format.
To transition to Cinemachine 3, refer to Upgrade a Project from Cinemachine 2.x. To continue using Cinemachine 2, you must update the manifest of your project to reference a local copy of Cinemachine 2.
Editor and workflow
This section outlines recent updates to the Unity Editor and its general workflows that can affect your upgrade experience.
YAML file format change
Word wrapping is disabled in YAML text files and the Reduce Version Control Noise option has been removed from the Unity Editor settings.
Reduce Version Control Noise was previously enabled by default, which disabled word wrapping of references in YAML files. Because of this, most projects already had word wrapping disabled.
The equivalent API, setter is now a no-op and the getter always returns true.
serializeInlineMappingsOnOneLineThe impact of this change is that you might see changes to YAML files that appear unrelated to any changes you made to your assets.
To prevent multiple contributors from experiencing these changes, consider reserializing all your assets. For more information, refer to the API.
ForceReserializeAssetsGraphics
This section outlines recent updates to graphics that can affect your upgrade experience.
Removed dynamic batching
Dynamic batching is now obsolete. For information about other methods of optimizing draw calls, refer to Choose a method for optimizing calls.
Render Pipeline Core no longer depends on Terrain
Removed the dependency on package from the package. If your project relies on Terrain indirectly through the Render Pipeline Core, Universal Render Pipeline, or High Definition Render Pipeline packages, add the package to your project through the Package Manager > Built-in tab. Terrain is still included in new projects’ dependencies by default.
com.unity.modules.terraincom.unity.render-pipelines.corecom.unity.modules.terrainRemoved Rendering Debugger legacy state management
The legacy Debug UI infrastructure in the package is now obsolete. Using these APIs now triggers an attribute, resulting in compilation errors. This change affects , , legacy implementations, and their associated types. You must migrate any projects using these features to the current Rendering Debugger pattern.
com.unity.render-pipelines.core[Obsolete(..., true)]DebugStateDebugState<T>DebugUIDrawerThe following APIs no longer compile:
- Debug State classes: ,
DebugState, and all concrete implementations (such asDebugState<T>,DebugStateBool,DebugStateInt,DebugStateFloat, andDebugStateColorvariants).DebugStateVector - Legacy Debug UI Drawers: All older custom drawer implementations.
DebugUIDrawer - Supporting types: and
DebugStateAttribute.LegacyStyles
To upgrade your code, follow these steps:
-
Implementon your debug settings classes.
ISerializedDebugDisplaySettingsIf your debug settings class previously relied onfor serialization, you must now implementDebugState. This interface allows for automatic serialization via theISerializedDebugDisplaySettings.DebugDisplaySerializerThe following example demonstrates implementing:ISerializedDebugDisplaySettings[Serializable]public class MyDebugSettings : IDebugDisplaySettingsData, ISerializedDebugDisplaySettings{ public bool myFeatureEnabled; void IDebugDisplaySettingsData.Reset() { myFeatureEnabled = false; }} -
Implement themethod for custom
Createimplementations.DebugUI.WidgetCustom widgets that formerly usedfor rendering must now implement the abstractDebugUIDrawermethod to return theirCreate.VisualElementThe following example demonstrates a customimplementation with theDebugUI.Widgetmethod:Createpublic class MyCustomWidget : DebugUI.Widget{ protected override VisualElement Create() { var container = new VisualElement(); // Use UI Toolkit to build your UI here return container; }}
The Rendering Debugger now handles calls internally, which in turn executes your defined logic.
ToVisualElementCreateSurface shader code generation now uses caching preprocessor
Surface shader code generation now uses the caching preprocessor. For information about the preprocessor behavior changes, refer to the New shader preprocessor Discussions post.
Deprecated Progressive CPU Lightmapper
The Progressive CPU Lightmapper is now deprecated and will be removed in a future release. Existing projects can continue to bake with it, but the recommended best practice is to migrate to the Unity Compute Light Baker or the Progressive GPU Lightmapper.
Baked lighting might look different after you change the backend, so review and adjust your lighting setup after you migrate. For more information, refer to Choose a light baking backend and Unity Compute Light Baker.
Optimization
This section outlines recent updates to optimization that can affect your upgrade experience.
Performance testing API is a core package
The package is now a core package and part of the Unity Editor. Any project that depends on this package now automatically uses the version that is part of the Editor.
com.unity.test-framework.performancePlatforms
This section outlines recent updates to platform-specific tools and settings that can affect your upgrade experience.
Android
This section outlines recent updates to Android-specific tools and settings.
Removed Legacy and Round icons
Removed support for Legacy and Round Android icons. Unity now supports only Adaptive Android icons.
When you upgrade a project that uses Legacy and Round Android icons, Unity displays a warning message and excludes these icons from Android builds.
To update your icon settings, follow these steps:
- Open Edit > > Player > Android > Icon.Project Settings
?
- Verify your Adaptive icon settings.
You can remove any unused Legacy and Round icon assets from your project. The warning clears when you open the Player settings.
Removed legacy chained signal handler behavior on Android
The option for the command-line argument has been removed from the Android Player runtime. This option was added as a workaround for older Android versions that didn't handle native crash reporting. This behavior handled native crashes, such as SIGSEGV at JNI boundaries using and functions, and wrapped them into Java exceptions. This approach is now obsolete because app stores, such as the Google Play Console, now handle native crashes directly. Furthermore, this legacy behavior prevented third-party crash-reporting SDKs, such as Firebase Crashlytics or Bugsnag, from receiving signals. This caused background worker threads to stop responding upon crashing.
legacy-androidChainedSignalHandlerBehaviorsetjmplongjmpIn Unity 6.6, the option has been fully removed. If you explicitly pass as a command-line argument, Unity now does the following:
legacylegacy- Logs an error to Logcat: .
ChainedSignalHandler: Legacy behavior has been removed. The default chained signal handler behavior will be used instead - Uses the default chained signal handler behavior instead of the legacy behavior.
Refer to the following based on your project setup:
- Command-line fallback: If your build pipelines, launch scripts, or custom Activity templates still pass , Unity doesn't fail to boot and automatically falls back to the default behavior. However, it logs an error in Logcat. Remove this obsolete argument to keep your logs clean.
-androidChainedSignalHandlerBehavior legacy - Java exception handling: If your application framework relied on capturing native crashes inside Java try/catch blocks at the JNI boundary, the legacy behavior is no longer available. Native crashes now terminate the process and are handled as standard native signals.
- Crash reporting and multithreading: Native crash handlers, including Unity Cloud Diagnostics and third-party tools, now capture native crashes across all threads. This includes background worker threads and Java-invoked threads, which previously didn't report crashes.
Raised minimum supported OpenGL ES version for Android from GLES 3.0 to GLES 3.1
The minimum OpenGL ES version on Android is now ES 3.1, raised from ES 3.0.
When you select OpenGL ES3 in the Android Graphics API list, the following occurs:
- The generated manifest declares .
<uses-feature android:glEsVersion="0x00030001" /> - The Player no longer creates an ES 3.0 context at runtime.
- Devices that support only ES 3.0 and do not support Vulkan can no longer run the app, as the Play Store filters them out and initialization fails on-device.
You cannot revert to ES 3.0.
PlayerSettings.openGLRequireES31trueFor compatibility reasons, if your project never used Require ES3.1 or similar, the upgraded project automatically enables Use OpenGL ES 3.0 shaders. This gives you the option to upgrade OpenGL ES 3.0 shaders to version 3.1 as needed, preventing visual artifacts that might otherwise occur if Unity forced OpenGL ES 3.1 shaders. For example, OpenGL ES 3.1 shaders raise the limit from 16 to 32, which increases the application's workload. The Use OpenGL ES 3.0 shaders setting provides a transition period so you can adapt to these changes without causing performance regressions in your upgraded project.
MAX_VISIBLE_LIGHTSTo update your code for this change, follow these steps:
- Remove calls to . ES 3.1 is now implied whenever OpenGL ES3 is selected.
PlayerSettings.openGLRequireES31 - Disable Player > Android > Other Settings > Use OpenGL ES 3.0 shaders to use SHADER_API_GLES31 shader keyword instead of SHADER_API_GLES30.
- To require a higher version, use or
PlayerSettings.openGLRequireES31AEP, or enable the Require ES3.1+AEP or Require ES3.2 checkboxes in Player > Android > Other Settings.openGLRequireES32
Programming
This section outlines recent updates to the Programming system that can affect your upgrade experience.
UNITY_64 and DEVELOPMENT_BUILD scripting symbols are deprecated
The and preprocessor symbols are deprecated, and C# diagnostics now follow the Managed Code Variant setting. These updates involve the following:
UNITY_64DEVELOPMENT_BUILD-
Added a new Managed Code Variant setting. This per-platform setting controls which diagnostic defines are emitted into your C# code, independently of the native binary. To access it, go to Edit > Project Settings > Player > Other Settings > Managed Code Variant. For a list of the variants and the defines they emit, refer to Adding diagnostics to C# code.
- replaces the extra safety checks and assertions meaning of
UNITY_ENABLE_CHECKS, andDEVELOPMENT_BUILDreplaces the profiling and diagnostic logging meaning. This enables profiling without any diagnostics checks.UNITY_INCLUDE_INSTRUMENTATION - The variant can also be read or set from build scripts with and
PlayerSettings.GetManagedCodeVariant.PlayerSettings.SetManagedCodeVariant - In the Editor, both and
UNITY_ENABLE_CHECKSare always defined.UNITY_INCLUDE_INSTRUMENTATIONandUNITY_ASSERTIONShave historically been defined for development builds, and continue to be defined during this transitional period.ENABLE_PROFILER
-
Deprecatedand
UNITY_64scripting symbols. Using either symbol in anDEVELOPMENT_BUILDdirective or a#ifattribute now raises a Roslyn analyzer warning ([Conditional(...)]forUAC0008,UNITY_64forUAC0009) in the Console and in your IDE.DEVELOPMENT_BUILD
Impact of not updating your code
In Unity 6.6, the and defines continue to work. Unity displays deprecation warnings but is still emitted for development builds, so your project still works at runtime. However, if your assemblies are compiled with warnings as errors, the warnings become build errors immediately.
UNITY_64DEVELOPMENT_BUILDDEVELOPMENT_BUILDIn Unity 6.8, these defines will be fully removed. Using them will become a hard compilation error and will no longer be emitted by the compilation pipeline. If you migrate now, you can update your codebase incrementally.
DEVELOPMENT_BUILDBehavior impact in your project
If you never used these defines, your project is still impacted by these changes. Many built-in features and packages previously used internally and now use the Managed Code Variant setting instead. Unity includes these features based on the option you set for Managed Code Variant, instead of the setting. The default option is Release, which defines none of the diagnostic symbols, so a Development Build using the default variant no longer contains these diagnostics. The affected features include the following:
DEVELOPMENT_BUILDDevelopment Build
?
- Scriptable Render Pipeline (URP/HDRP/Core): Debug overlays, 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 (Debug/Checked). Render Graph profiling samplers, URP's per-pass
UNITY_ENABLE_CHECKS, and HDRP's dynamic-resolution overlay are gated byScriptableRenderPass.profilingSampler(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. As a side effect, non-development Release builds no longer ship debug-display shader variants they previously included, reducing build size and shader-variant count.UNITY_INCLUDE_INSTRUMENTATION - Unity Physics: Simulation integrity checks are now compiled in for the Debug/Checked variants. You can still override the checks with .
UNITY_PHYSICS_DISABLE_INTEGRITY_CHECKS - Entities: Entities Journaling, the data behind the Entities Journaling window, is now compiled in for Debug, Checked, and Instrumented variants. You can still override it with .
DISABLE_ENTITIES_JOURNALING - Adaptive Performance: Apple and Android provider logging is now available in Debug, Checked, and Instrumented variants.
To achieve the diagnostic behavior that a Development Build previously provided, set the Managed Code Variant to Checked (which enables both the check and instrumentation paths) for the platforms where you enable the Development Build checkbox. Use Debug if you also want and unoptimized code for stepping through with a debugger.
DEBUGIf you have a custom Scriptable Render Pipeline with build processors that read , this property is now and always returns . Use instead.
CoreBuildData.developmentBuild[Obsolete]falseCoreBuildData.useDiagnosticChecksUpdate your code
-
Replace. The bitness of the native binary is not known when scripts are compiled, so replace any compile-time
UNITY_64with a runtime check on#if UNITY_64(IntPtr.Size= 64-bit,8= 32-bit), or with bitness-independent code.4For example, the following code usesat compile time:UNITY_64#if !UNITY_64 && UNITY_ANDROID return HashWithoutUnalignedLoads(buffer, length);#else return HashWithUnalignedLoads(buffer, length);#endifReplace it with the following runtime check on:IntPtr.Size#if UNITY_ANDROID if (IntPtr.Size == 4) return HashWithoutUnalignedLoads(buffer, length);#endif return HashWithUnalignedLoads(buffer, length); -
Replace:
DEVELOPMENT_BUILD-
If the code was for safety checks, validation, assertions: use(Debug/Checked).
#if UNITY_ENABLE_CHECKSFor example, the following check runs only in the Editor or a development build:#if UNITY_EDITOR || DEVELOPMENT_BUILD SafetyChecks.CheckAlignmentAndThrow(ptr, nameof(ptr));#endifReplace the condition with:UNITY_ENABLE_CHECKS#if UNITY_ENABLE_CHECKS SafetyChecks.CheckAlignmentAndThrow(ptr, nameof(ptr));#endif
Compound gates such asbecome#if UNITY_EDITOR || DEVELOPMENT_BUILD. Because the Editor already defines the new symbols, you can usually drop the redundant#if UNITY_EDITOR || UNITY_ENABLE_CHECKSpart.UNITY_EDITOR ||-
If the code was for profiler instrumentation, debug names, or diagnostic logging: use(Debug/Checked/Instrumented), or layer it onto a
#if UNITY_INCLUDE_INSTRUMENTATIONattribute:[Conditional]For example, the following method is conditional on:DEVELOPMENT_BUILD[Conditional("DEVELOPMENT_BUILD")]public static void LogDiagnostic(string message) { ... }Replace the symbol in the attribute:[Conditional("UNITY_INCLUDE_INSTRUMENTATION")]public static void LogDiagnostic(string message) { ... } -
A runtime check for a development Player: use the runtime property. This is the correct choice when the new variant defines are not equivalent. For example, a non-development Player can ship with the Checked variant, so a
Debug.isDebugBuildblock would compile sensitive code, such as logging that might leak authentication tokens, into a production build.#if UNITY_ENABLE_CHECKSFor example, the following log call previously shipped only in the Editor or a development build:#if UNITY_EDITOR || DEVELOPMENT_BUILD Debug.LogError($"Rejecting connection: {payload}");#endifReplace the compile-time check with the runtime check:if (Debug.isDebugBuild) Debug.LogError($"Rejecting connection: {payload}");
-
-
Choose the Managed Code Variant for each platform: In Edit > Project Settings > Player > Other Settings > Managed Code Variant, select the variant whose diagnostics you want in your Player builds (Release for shipping; Checked or Debug while developing). From a build script, call.
PlayerSettings.SetManagedCodeVariant(namedBuildTarget, ManagedCodeVariant.Checked) -
Replace: This enum value is now
BuildOptions.ForceEnableAssertions. Use[Obsolete]instead.PlayerSettings.SetManagedCodeVariant(namedBuildTarget, ManagedCodeVariant.Checked)
To make sure your code compiles against multiple Unity versions
For package and Asset Store authors whose code also targets Unity versions older than 6.6, where the new defines don't exist, gate on and fall back to a runtime check. This lets you keep the diagnostic body written once:
UNITY_6000_6_OR_NEWERDebug.isDebugBuild#if !UNITY_6000_6_OR_NEWER || UNITY_ENABLE_CHECKS#if !UNITY_6000_6_OR_NEWER if (Debug.isDebugBuild)#endif { // diagnostic body, written exactly once if (library == null) Debug.LogWarning("No library assigned."); }#endif
For methods, select the attribute per Unity version:
[Conditional]#if UNITY_6000_6_OR_NEWER[Conditional("UNITY_INCLUDE_INSTRUMENTATION")]#else[Conditional("DEVELOPMENT_BUILD")]#endifstatic void LogDiagnostic(...) { ... }
For more information, refer to Adding diagnostics to C# code, , and the Unity scripting symbol reference documentation.
ManagedCodeVariantDictionary serialization works alongside existing dictionary solutions
Unity 6.5 and earlier versions didn't support serializing fields declared as . A common alternative solution was a wrapper type that derives from it, or a class that stores parallel key and value lists and rebuilds the dictionary in .
Dictionary<TKey, TValue>[Serializable]ISerializationCallbackReceiver.OnAfterDeserializeUnity 6.6 serializes a field whose declared type is when it has . A field whose declared type derives from , or wraps it in another class, remains a regular serialized class handled by the callback code it already uses. Those solutions keep working without changes, whether the type is one you wrote or one that comes from a package. You can use serialized dictionaries in new code and leave your existing fields as they are.
Dictionary<TKey, TValue>[SerializeField]Dictionary<TKey, TValue>If you choose to migrate a field to Unity's dictionary serialization, you must migrate its data yourself. Add the new field alongside the old one, copy the data across from an editor script, and delete the old field only after you have checked the result. If you delete the old field first, its data is lost. For the full procedure, refer to Migrate a custom dictionary solution to built-in dictionary serialization.
For more information, refer to Dictionary serialization.
UI Toolkit
This section outlines recent updates to Unity’s UI Toolkit that can affect your upgrade experience.
Removed DefaultEventSystem.LegacyInputProcessor
The has been removed. As a result, the obsolete method now produces an error in projects that use it. You can safely ignore this error, but remove any remaining calls to that method from your project. You do not need to replace it with anything, as the method no longer has an effect.
DefaultEventSystem.LegacyInputProcessorUIToolkitInputConfiguration.SetRuntimeInputBackendRemoved UXML Factory/Traits
In Unity 6.0, UI Toolkit introduced a modern UI element authoring system based on and , powered by Unity serialization. This new system replaces the legacy UXML Factory/Traits workflow, which was deprecated and is now removed.
UxmlElementUxmlAttributeWhile the legacy system was supported for backward compatibility, maintaining dual workflows has created bugs, confusion, and long-term costs. The new system offers a cleaner, more robust, and consistent UI experience, so we’re moving forward with it exclusively.
For more information and examples, refer to Migrate custom controls from an earlier version to Unity 6, Custom controls documentation and API reference.
UxmlElementAttribute