Hi everyone,
As we did with Unity 6.5, here is some early notice about upcoming breaking changes we plan to make in Unity 6.6.
While our goal is for every release in the 6.x series to be a completely seamless upgrade experience, we also need to balance that goal against the need to evolve the product, both in response to external changes in our platforms and ecosystem, and as part of our long-term product roadmap. So, we’re making a few changes that may require a little bit of upgrade work on your part.
We’re sharing this now so that you can plan any needed work, and to give you the opportunity to let us know if there is some aspect of the change we haven’t considered. We don’t guarantee that every intentional breaking change is captured here, but we’ll cover as much as we can.
In addition to these changes, you may also want to read the CoreCLR Upgrade Guide, which discusses some of the breaking changes we expect to make over the course of this year as we progress towards our delivery of the CoreCLR runtime. Most of what we have described there will not impact you until Unity 6.8, but we recommend removing problematic patterns from your projects early, so that you’re able to more easily upgrade to 6.8 and get the benefits of CoreCLR once it is released.
You may want to ‘Watch’ this thread, so that you can be notified when updates are posted.
Minimum OpenGLES version raised to 3.1
In Unity 6.6, OpenGLES 3.0 will be no longer supported on Android. The minimum supported OpenGLES version will be 3.1. Projects that target older Android devices with OpenGLES 3.0-only support, or that explicitly force OpenGLES 3.0 at startup, will no longer launch on those devices after upgrading.
Before upgrading, review your device analytics to see whether these devices are still part of your player base; our own data suggests that OpenGLES 3.0 devices only make up about 0.4% of players, mostly on very old Adreno 300 GPUs, but your own project’s demographics may be different, and if it is an issue for you, you may want to postpone upgrading.
Most Android devices supported by Unity already provide OpenGLES 3.1 or higher, so this change is unlikely to affect most projects.
Android legacy chained signal handler support removed
Wrapping native crashes as Java Exceptions, using the legacy value for -androidChainedSignalHandlerBehavior, is no longer supported by Unity. This is due to crash handling and reporting services (including Google Play) fully supporting native crashes.
If you have code that relies on Java Exception wrapped native crashes then this will no longer function, and native crashes will be handled by Android or any third party services.
Denoising changes
These changes have been delayed, and will not be in Unity 6.6
Following the marking of the Optix denoiser as obsolete in Unity 6.5, we are fully removing it in 6.6. The OpenImage denoiser produces consistently better quality denoising, has broader platform reach, and better performance due to its ability to leverage optimized GPU paths on all supported Editor platforms, compared to Optix which is only able to leverage NVidia GPUs on Windows x64 in Unity.
Projects that are currently using the Optix denoiser will be automatically updated to use OpenImage. As noted, in general this should result in lighting with better quality denoising, but we consider it a breaking change as it does mean that the output will not be exactly the same as before.
In addition, we are moving the OpenImage denoiser to an engine module. This will make the com.unity.rendering.denoising package no longer necessary, simplifying your workflows and making it easier for us to move faster in our development. Code using the denoiser APIs should not need to be modified, though any precompiled assemblies referencing the APIs may need to be rebuilt, and you may want to clean up any left over references to the packages or assembly definition files.
Removal of Rendering Debugger DebugState serialization system
In Unity 6.5, we migrated Rendering Debugger UI from IMGUI/uGUI to UI Toolkit. With this change, we also introduced the new state serialization system based on the ISerializedDebugDisplaySettings interface, while keeping the old DebugState state serialization system functional. Now we are removing this old system. If you are adding custom panels to Rendering Debugger using the DebugUI API as described in this example, you will need to update your code to ensure the debug setting state is serialized (e.g. keep selected debug settings when entering play mode). To achieve this, follow these steps:
- Place the debug settings values that need to be serialized inside a new class that is marked
[Serializable]. - Inherit the class from
ISerializedDebugDisplaySettings. - In order to use the data, retrieve it using
DebugDisplaySerializer.GetOrCreate<T>().
By following these steps, the settings will be automatically serialized on domain reload instead of reverting to default values.
Refer to the updated example page in Unity 6.5 documentation for a complete example.
UIToolkit “set input backend” method removed
The obsolete method UIToolkitInputConfiguration.SetRuntimeInputBackend will now produce an error in projects that are using it. That error can be safely ignored but users are strongly encouraged to remove any remaining call to that method. There is no need to replace it with anything, as that method now has no effect at all.
Deprecation / Removal of low-level internal Content Build APIs
Some low-level Content Build APIs have been removed or marked as obsolete. Though they were marked as public, these APIs were really intended for internal use by the Scriptable Build Pipeline package only (and were documented as such). The SBP never actually ended up using them, so we’re cleaning them up.
Removal of UxmlFactory/UxmlTraits
This change was originally announced for Unity 6.4, but did not make the release in time. We now expect to make it in Unity 6.6.
In Unity 6.0, UI Toolkit introduced a modern UI element authoring system based on UxmlElement and UxmlAttribute, powered by Unity serialization. This new system replaces the legacy UXML Factory/Traits workflow, which has been deprecated and will now be removed.
While the legacy system was supported for backwards 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.
The Unity Manual contains a migration guide. Further documentation and examples can be found in the manual and API reference.
Removal of experimental AssetDatabase on-demand import APIs
The experimental AssetDatabaseExperimental.OnDemandMode enum and AssetDatabaseExperimental.ActiveOnDemandMode property have been removed. These APIs were part of an incomplete on-demand import mode that was never fully implemented or documented. If your project references these APIs, remove the calls. There is no replacement — the on-demand import mode was not functional in production.
No further action is required. The default Asset Database import behaviour is unchanged.
Unity.Hierarchy Obsolete APIs Now Generate Errors
49 APIs in the Unity.Hierarchy namespace that were marked obsolete in Unity 6.0, 6.3, and 6.5 now generate compile errors instead of warnings. These APIs will be completely removed in Unity 6.7.
If your project uses any of these APIs, you will receive compile errors with clear messages indicating the replacement API to use. All replacement APIs are already available.
Affected APIs:
Hierarchy class:
GetAllNodeTypeHandlersBase()→ UseEnumerateNodeTypeHandlersBase()GetAllNodeTypeHandlersBase(List<HierarchyNodeTypeHandlerBase>)→ UseEnumerateNodeTypeHandlersBase()GetAllNodeTypeHandlersBaseCount()→ UseEnumerateNodeTypeHandlersBase()RegisterNodeTypeHandler<T>()→ Renamed toGetOrCreateNodeTypeHandler<T>()SortChildren(in HierarchyNode, bool)→ UseSortChildren(node)orSortChildrenRecursive(node)UnregisterNodeTypeHandler<T>()→ No longer has any effect
HierarchyCommandList class:
SortChildren(in HierarchyNode, bool)→ UseSortChildren(node)orSortChildrenRecursive(node)
HierarchyFlattened class:
Hierarchyproperty → Will be removed in the future
HierarchyFlattenedNodeChildren struct:
- Entire struct replaced by
HierarchyFlattenedChildrenEnumerable
HierarchyNodeTypeHandlerBase class:
HierarchyNodeTypeHandlerBase(Hierarchy)constructor → Use parameterless constructorChangesPending()→ Add commands toCommandListinsteadDispose()→IDisposableinterface no longer neededIntegrateChanges(HierarchyCommandList)→ Add commands toCommandListinstead
HierarchyViewModel class:
ClearFlags(in HierarchyNode, HierarchyNodeFlags, bool)→ UseClearFlags(node, flags)orClearFlagsRecursive(node, flags, direction)DoesNotHaveAllFlags(HierarchyNodeFlags)→ UseDoesNotHaveFlags()DoesNotHaveAllFlags(in HierarchyNode, HierarchyNodeFlags)→ UseDoesNotHaveFlags()DoesNotHaveAllFlagsCount(HierarchyNodeFlags)→ UseDoesNotHaveFlagsCount()DoesNotHaveAnyFlags(HierarchyNodeFlags)→ UseDoesNotHaveFlags()DoesNotHaveAnyFlags(in HierarchyNode, HierarchyNodeFlags)→ UseDoesNotHaveFlags()DoesNotHaveAnyFlagsCount(HierarchyNodeFlags)→ UseDoesNotHaveFlagsCount()EnumerateNodesWithAllFlags(HierarchyNodeFlags)→ UseEnumerateNodesWithFlags()EnumerateNodesWithAnyFlags(HierarchyNodeFlags)→ UseEnumerateNodesWithFlags()EnumerateNodesWithoutAllFlags(HierarchyNodeFlags)→ UseEnumerateNodesWithoutFlags()EnumerateNodesWithoutAnyFlags(HierarchyNodeFlags)→ UseEnumerateNodesWithoutFlags()GetIndicesWithAllFlags(HierarchyNodeFlags, Span<int>)→ UseGetIndicesWithFlags()GetIndicesWithAllFlags(HierarchyNodeFlags)→ UseGetIndicesWithFlags()GetIndicesWithAnyFlags(HierarchyNodeFlags, Span<int>)→ UseGetIndicesWithFlags()GetIndicesWithAnyFlags(HierarchyNodeFlags)→ UseGetIndicesWithFlags()GetIndicesWithoutAllFlags(HierarchyNodeFlags, Span<int>)→ UseGetIndicesWithoutFlags()GetIndicesWithoutAllFlags(HierarchyNodeFlags)→ UseGetIndicesWithoutFlags()GetIndicesWithoutAnyFlags(HierarchyNodeFlags, Span<int>)→ UseGetIndicesWithoutFlags()GetIndicesWithoutAnyFlags(HierarchyNodeFlags)→ UseGetIndicesWithoutFlags()GetNodesWithAllFlags(HierarchyNodeFlags, Span<HierarchyNode>)→ UseGetNodesWithFlags()GetNodesWithAllFlags(HierarchyNodeFlags)→ UseGetNodesWithFlags()GetNodesWithAnyFlags(HierarchyNodeFlags, Span<HierarchyNode>)→ UseGetNodesWithFlags()GetNodesWithAnyFlags(HierarchyNodeFlags)→ UseGetNodesWithFlags()GetNodesWithoutAllFlags(HierarchyNodeFlags, Span<HierarchyNode>)→ UseGetNodesWithoutFlags()GetNodesWithoutAllFlags(HierarchyNodeFlags)→ UseGetNodesWithoutFlags()GetNodesWithoutAnyFlags(HierarchyNodeFlags, Span<HierarchyNode>)→ UseGetNodesWithoutFlags()GetNodesWithoutAnyFlags(HierarchyNodeFlags)→ UseGetNodesWithoutFlags()HasAllFlags(HierarchyNodeFlags)→ UseHasFlags()HasAllFlags(in HierarchyNode, HierarchyNodeFlags)→ UseHasFlags()HasAllFlagsCount(HierarchyNodeFlags)→ UseHasFlagsCount()HasAnyFlags(HierarchyNodeFlags)→ UseHasFlags()HasAnyFlags(in HierarchyNode, HierarchyNodeFlags)→ UseHasFlags()HasAnyFlagsCount(HierarchyNodeFlags)→ UseHasFlagsCount()Hierarchyproperty → Will be removed in the futureHierarchyFlattenedproperty → Will be removed in the futureSetFlags(in HierarchyNode, HierarchyNodeFlags, bool)→ UseSetFlags(node, flags)orSetFlagsRecursive(node, flags, direction)ToggleFlags(in HierarchyNode, HierarchyNodeFlags, bool)→ UseToggleFlags(node, flags)orToggleFlagsRecursive(node, flags, direction)
HierarchyViewNodesEnumerable struct:
- Entire struct renamed to
HierarchyViewModelNodesEnumerable
Raising minimum supported Cinemachine version
Cinemachine 3 is now the default Cinemachine version compatible with the Editor.
Cinemachine 2 will stay available on the repository https://github.com/Unity-Technologies/com.unity.cinemachine, and you will be able to download it, or fork it, if you want. However, we won’t guarantee that it works with Unity 6.5 and the subsequent releases, nor will we fix Cinemachine 2 bugs for those Editor versions.
We will continue to support Cinemachine 2 for the duration of Unity 6.3 LTS.
If you want to migrate from Cinemachine 2 to 3, there is a transition guide available here: https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/manual/CinemachineUpgradeFrom2.html
Input system migrated to built-in package
These changes have been delayed, and are now planned for Unity 6.7
The Input System is now a Unity Engine built-in package and not an optional package. This means that any dependencies looking for the presence of the package in the project need to be updated.
If you have an Assembly Definition in your project or package that uses Version Define like the following example, or you are making checks against the existence of the com.unity.inputsystem package, you will need to adjust how you identify if the Input System is available and active.
{
"name": "com.unity.inputsystem",
"expression": "1.0.0-preview",
"define": "PACKAGEX_UNITY_INPUTSYSTEM"
},
Scripts which are guarded with this #if PACKAGEX_UNITY_INPUTSYSTEM will have those particular code paths compiled only if the package is present. Ideally, this pattern should be replaced. From 6.6, the package no longer exists in new projects so this check will be ignored even though the Input System module is available. This results in these code paths not being compiled and thus not executed at runtime.
The recommended way to know if Input System is enabled is by checking for ENABLE_INPUT_SYSTEM as explained in Installation guide | Input System | 1.18.0. So one will have to replace the previous .asmdef define with this define instead.
For new projects adding packages with soft dependencies using Assembly Definition Version Defines, one should expect warnings such as the one below.
For project upgrades purposes when a project or package has a hard dependency on the Input System package, a “shim package” will be used instead. This is to facilitate upgrades of existing projects. In this case, you will see an “empty” Input System package in your Package Manager with version 2.0.0.
AR Module Removal
This change was originally planned for 6.6, but has been delayed to 6.7
Unity’s AR Module will be removed starting from Unity 6.6. To access any AR Core functionality, please continue to use the ARCore XR Plug-in package.
As a part of this change, UnityEditor.PlayerSettings.Android.ARCoreEnabled and UnityEngine.LowLevel.PlayerLoop.ARCoreUpdate will no longer be available. These symbols haven’t done anything for a while, so you should be able to simply delete any code which is still using them.
Dynamic Batching removal
Unity has a very old graphics feature called ‘dynamic batching,’ which combines meshes on the CPU in order to reduce draw calls. (To be clear, this is entirely separate from the SRP batcher).
For some years now, the cost of combining the meshes and uploading the result to the GPU has been higher than the cost of the draw calls, making the feature a net loss for performance. In Unity 6.5 we formally marked the feature as deprecated, and in Unity 6.6 we will remove it entirely.
Netcode for Entities config singleton now created always
This change has been delayed, and is now planned for Unity 6.7
In Netcode for Entities projects, the NetcodeConfig singleton instance is now generated automatically for all projects, and so calling EntityManager.CreateSingleton<NetcodeConfig>() to create the singleton explicitly will now fail with an error saying that the singleton has already been created. You can update your code to use SystemAPI.GetSingleton<NetcodeConfig>() instead.
If you are using CreateSingleton<NetcodeConfig>() to configure ClientServerTickRate, ClientTickRate and GhostSendSystemData, you will still be able to keep configuring those settings in code at runtime as NetcodeConfig won’t override those after it has seeded your netcode worlds.
