Planned breaking changes in Unity 6.7

Hi everyone,

As we did with Unity 6.6, here is some early notice about upcoming breaking changes we plan to make in Unity 6.7.

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.

The thread will be updated as more breaking changes are identified. You may want to ‘Watch’ this thread, so that you can be notified when updates are posted.


OculusXR Package Removal

Following its deprecation in Unity 6.5, we are fully removing the OculusXR package from Unity 6.7. Projects using the package that upgrade to Unity 6.7 will have the package automatically removed.

The OpenXR Meta package is the recommended path for building Meta Quest experiences. We encourage developers to migrate or start their new projects on Quest platforms with the OpenXR Meta package, which achieved parity with OculusXR as of OpenXR 1.14. This provides you with a more cross-platform development experience, with access to features like Shared Spatial Anchors, Occlusion and more.

Windows Player now links the C runtime dynamically

Starting in Unity 6.7, binaries in Windows builds (UnityPlayer.dll, the game executable, UnityCrashHandler64.exe, Mono’s mono-2.0-bdwgc.dll and MonoPosixHelper.dll and IL2CPP’s GameAssembly.dll) will link the Microsoft Visual C++ runtime dynamically instead of statically. To support this, Unity now copies the Microsoft Visual C++ Redistributable DLLs (such as vcruntime140.dll, vcruntime140_1.dll, and msvcp140.dll) into your build output, alongside UnityPlayer.dll. You can optionally disable copying of the Visual C++ Redistributable DLLs to your build output if you plan to instead use a system-wide Visual C++ redistributable installer. The Universal CRT is part of Windows 10 and later (the supported minimum), so it is not shipped.

Why: this aligns Windows with every other Unity platform, lets Microsoft security fixes to the C runtime be applied without rebuilding your game, and removes duplicated runtime code from each binary.

What you need to do:

• Most projects: nothing. If you distribute the entire build output folder (the default), the required DLLs are already included.

• If you use a custom installer, packaging script, patch system, or otherwise ship only a subset of the build folder: make sure the new redistributable DLLs are included next to UnityPlayer.dll. They are required: treat them exactly like UnityPlayer.dll. If they are missing, the game will fail to start with a Windows error such as “The code execution cannot proceed because VCRUNTIME140.dll was not found.” on machines that do not have a system-wide Visual C++ redistributable package installed.

• If you ship native (C/C++) plugins: you may rebuild your plugins to use dynamic C runtime without worrying about redistributing Visual C++ redistributable DLLs. Do not ship an older copy of vcruntime140.dll/vmsvcp140.dll next to the player, as it can override the version Unity needs.

Restrictions on serialized data structure patterns

We are hardening the serialization system to clarify correct usage patterns, to help prevent unexpected errors or data loss, and to prepare the system for future evolution. To aid with this, we are adding warnings, errors, code analyzers, and improved documentation to provide the necessary guidance on correct usage patterns and how to fix mistakes.

While working on this process, we came across two particularly bad cases with direct self-reference cycles in serialized classes. We introduced warnings to highlight these in Unity 6.5, and starting with Unity 6.7 these will be compile errors that you must address in your code.

The first case is when a serializable type has a field of its own type, for example:

[Serializable]
public class SelfReference
{
    public SelfReference o_Ref;
}

In this case, Unity silently ignored the o_Ref field, meaning that the data is not serialized at all. From Unity 6.5, we reported compiler warnings UAC1005 and UAC1006; in Unity 6.7, these will be changed from warnings to errors.

The second case is when types have mutual references leading to a cycle, for example:

[Serializable]
public class IndirectReference
{
    public OtherReference o_Ref;
}

[Serializable]
public class OtherReference
{
    public IndirectReference i_Ref;
}

When using these types in a MonoBehaviour or ScriptableObject, you would previously have seen a console error about the “serialization depth limit” indicating that a cycle is present. From Unity 6.5, we detected this case and reported compiler warnings UAC1007 and UAC1008; in Unity 6.7, these will be changed from warnings to errors.

In both cases, the issue can be resolved by using the [SerializeReference] attribute.

Code in precompiled assemblies which uses these patterns will continue to load and run successfully, but we will fully remove support for serializing cyclic type definitions by value in a future version of Unity.

Note that this issue does not apply when the types involved inherit from UnityEngine.Object (for example, a MonoBehaviour or ScriptableObject), because such types are always serialized by reference, never by value.

For more information, please see the documentation for the serialization rules.

Denoising changes

These changes were originally announced for Unity 6.6, but were delayed to Unity 6.7; they have been delayed again and will not be in 6.7

Following the marking of the Optix denoiser as obsolete in Unity 6.5, we are fully removing it in 6.7. 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.

Input system migrated to built-in package

This change was originally announced for Unity 6.6, but was delayed to Unity 6.7

Update: Following your feedback, we will not be delivering this change as originally described. Instead, we will migrate InputSystem to a ‘core package’, shipping it in lock-step with Unity releases but keeping the majority of it as a package that you can continue to modify in your projects, similar to packages such as URP. You will be able to continue using Assembly Definition Version Defines based on the package presence / version as you do today, so no action should be needed.

While we do still need to migrate some foundational aspects of the package into the core of the engine (and so the code for those aspects will no longer be accessible), this approach will allow us to minimise the extent of the migration and preserve as much flexibility as possible for you. We do not expect to do any of this migration in 6.7, only in later releases.

The original description for this change is preserved below for reference.

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.

Netcode for Entities config singleton now created always

This change was originally announced for Unity 6.6, but was delayed to 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.

Removed deprecated Android ‘touch outside keyboard’ API

Following its deprecation in Unity 6.0, we are removing the obsolete TouchScreenKeyboard.Android.consumesOutsideTouches API. This setting enabled legacy Android keyboard behaviour where tapping outside the keyboard would always dismiss it, regardless of what was tapped. With the current behaviour, taps outside the keyboard are now always handled by the target control first, so users can tap another text field, button, or other touch-sensitive UI element while the keyboard remains open where appropriate.

AR Module removal

This change was originally planned for Unity 6.6 but has been delayed to Unity 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.

Deprecation and removal of very old APIs in Mecanim, Physics, Audio, Navmesh, and Timeline

We’re doing a clean-up of older obsolete APIs in Mecanim, Physics, Audio, Navmesh, and Timeline. This simplifies the API surface, removing noise from the API and associated things (like the API documentation), and helps to speed up our development processes a little.

This means we’ll be transitioning some old obsolete APIs from producing compiler warnings to producing compiler errors, and also fully removing several APIs that have been marked as obsolete with a compiler error. More than 160 APIs are affected, so we are not going to list them all here, but all of them have been marked as obsolete since before Unity 6.0 (and in the majority of cases, since before 2022 LTS).

For the APIs transitioning from ‘warning’ to ‘error’, if your project is still using them, you will now get compiler errors after upgrading. The compiler error message should explain what you need to do to fix your project.

For the APIs transitioning from ‘error’ to being fully removed, we don’t expect anyone to have been using them, as they produce compile errors today.

Clean up of Java engine classes

To improve security and better align with the intended API surface, we will restrict access to some internal Unity Java classes and methods. These classes were previously publicly accessible but were never intended for external use:

  • ApplicationExitInfoProvider
  • AudioVolumeHandler
  • Camera2Wrapper
  • GoogleARCoreApi
  • HFPStatus
  • MultiWindowSupport
  • NativeLoader
  • NetworkConnectivity
  • OrientationLockListener
  • PermissionRequest
  • PlatformSupport
  • StaticSplashscreen
  • UnityGameManager
  • UnityGameState
  • UnityPermissions
  • VideoPlayer
  • TimeoutThread
  • UnityPlayer.kbCommand
  • IFrameReady
  • IPermissionRequestCallbacks
  • VideoPlayer.StateCallback
  • ApplicationExitInfoBase
  • AudioVolumeObserver$OnAudioVolumeChangedListener
  • AudioVolumeObserver$OnAudioVolumeChangedListener
  • OnBackPressedDispatcher$OnBackPressedCallback
  • SystemSettingObserver$OnSystemSettingChangedListener
  • UnityPlayer.getNetworkProxySettings(java.lang.String)
  • UnityPlayer.startOrientationListener(int);
  • UnityPlayer.stopOrientationListener();
  • UnityPlayer.setMainSurfaceViewAspectRatio(float);
  • UnityPlayer$PhoneCallListener
  • UnityPlayer$kbCommand
  • UnityPlayerConfiguration.UnityPlayerConfiguration()
  • VideoPlayerProxy$PlayerDestructionCallback

Note that this change does NOT restrict access to the UnityPlayer class or its subclasses, which are the intended way to interact with Unity from your Android Java code, so we expect this change to impact very few users. For more information see the Unity Manual.

RenderGraph helper functions changes

Y-flip handling

We have updated the Rendergraph helper functions to fully support the UvOrigin feature, ensuring consistent y-flip handling across all platforms.

How this affects you: If you previously implemented manual workarounds in your scriptable render features to correct y-flip issues (specifically on platforms like Android), your rendered images may now appear flipped because the API is now handling this automatically.

Action required: If you notice incorrect image orientation in your project, please remove your manual y-flip workarounds. With this update, these manual corrections are no longer necessary and should be removed to ensure proper rendering.

Blit helper change

We have updated the Rendergraph blit helper functions so the default destination slice argument is -1 instead of 0.

How this affects you: In most use cases this may not make a difference. Only when rendering to array slice 0 it might make a difference. You will now need to explicitly indicate which slice to render to using the blit helpers.

Action required: Using -1 on arrays in a place where you should have used 0 will generally give a rendergraph error about the array layouts being incompatible. Change the value to 0.

iOS Minimum Supported Version raised from 15 to 16

In Unity 6.7 LTS we will update the minimum supported API required for running the iOS/tvOS/iPadOS Player to 16.

We expect this spec bump to impact a small number of 10+ year old devices and customers that are unable to upgrade to iOS 16. The number of devices impacted is projected to drop even lower over 2027.

Unity 6.0 and 6.3 will continue to support your projects at their existing minimum requirements.

28 Likes

/sidetopic :sadface:
that executable folder is already filled with all kind of “junk”, very difficult for average users who just want to run exe file.. (and folder has so many files and 2 exe files etc).

6 Likes

Yeah people always want to run CrashHandler for some reason

4 Likes

Yee, a solution I set up is to have a post-build processing that neatly puts everything in a subfolder and then have an exe-fied bat file outside as a launcher.

3 Likes

Remind me, can we use forks of built-in packages now, if we put them in the Packages/ folder? Or is that completely blocked? It did get blocked for scoped registries (boo), but I haven’t tried to fork one recently.

The Input System is one of those packages that we’ll often end up forking due to it being full of half-finished ideas and strange breakages. While it’s still miles ahead of the old input manager, modifying internals in the package is somewhere between “nice to have” and “required to ship”, depending on the needs of the particular game.

14 Likes

I’m afraid you there’s no easy way to do that (unless you have a source code license). It’s a somewhat unfortunate terminology thing, but “built-in package” is not really a package (we only ever call it that because it shows up in the Package Manager window in the ‘Built-In’ section), it’s a precompiled part of the engine core. As it’s mostly C#, the source should still be available to be viewed, but you can’t modify it directly.

3 Likes

Please call them Built-in Modules (they are literally under com.unity.modules), not Packages, this is very confusing!
I thought Input System is going to be tied to engine version like URP/Graphics packages, not become part of core modules

4 Likes

That’s pretty unfortunate! And a much bigger breaking change than what you hint at in the post.

I totally see that it’s required - if the old input system is ever to be removed, the new input system must be a part of the core of Unity, otherwise people won’t be able to have input. That’s not workable. So, yeah, down the line it should absolutely be core.

But right now, there’s a lot of value in being able to fork it. Not value as in “can make something cool and different”, but as in “can work around bugs and poor design”

As I said, we have been completely dependent on forking the Input package earlier to make input or rebinding be sane. I know that some of those issues got fixed, but we still run into issues in 6.3. And looking at the code while working on it, well, I don’t feel like it’s done?



Looking over some of those, it’s clear that somebody on the inside has/had a pretty clear idea of some of the pretty bad design choices and shortcomings of the system, and some of the things spelled out there absolutely cause us real problems that cost time and money.

So unless a ton of stuff happened behind the scenes since 1.19.0, which shipped February this year, moving the system to the core without end users having no ability to at least fork to fix, idk, it feels a bit premature. I know that “we should fix those things for everyone, you shouldn’t have to fork”, but are there any resources allocated to that?

Down the line, I also really would love it if you could allow us to replace the builtin packages that are pure C# baked into a dll with a fork that lives in our packages/ folder. One of the big improvements over the years to the Unity ecosystem has been the official packages’ forkability. That means that everything you do move into the core just immediately becomes worse. I know that the brief period where you could fork uitk while it was a part of the core was very bad, but I’m imagining that could probably be better when you don’t have to deal with Mono anymore?

26 Likes

Regarding the binding ID issue you mentioned in your other post, were you able to find that by debugging and stepping through code?

If so, I wonder how you’d be able to diagnose issues like that in the future with built-in packages/modules?

Also a +1 from me for wanting the ability to fork Unity modules to address a bug that absolutely needs fixing.

Just throwing my hat in the ring here to back up what Baste has to say. I’ve been happy with the breaking changes Unity has been making thus far, but I think being unable to fork the input system is a huge mistake.

I’ve been using a forked version of the input system package for years due to numerous issues, such as deselection behavior: Feature request: option to disable deselect in UI Input Module - #25 by WilsonCWong

These issues add up and affect the user experience directly. I might need to switch to Rewired if this is the case because as Baste says, some of the fixes and workarounds I do in my fork are “required to ship”.

4 Likes

With the officially provided C# packages, Unity has made a huge step forward from how it was >6 years ago when everything was part of the engine. My project would not be possible if the 2D packages were not modifyable.
Hope there won’t be more movement back in the direction of locking the packages by “integrating” them.

Why is it not possible to have necessary packages that yet can be modified?
Like sure, don’t let me open Unity if the C# files are missing or don’t compile, but still let me replace them please :slight_smile:

5 Likes

To add to confusion:

1 Like

Breaking changes seem to always end up being bigger than they appear to be on the surface. They affect different devs in different ways. For us, the input system change has been pretty easy to deal with. Other changes that some devs say is no big deal and just get over it, have, and continue to, cause us big headaches (like Unity changing core data types).

It really depends on your code base and what your various assets and projects do.

I’m glad Unity are pre-warning us, as they weren’t so great at this in the past, but they are still breaking changes… there will always be winners and losers.

Great addition! :grinning_face_with_smiling_eyes: I’ve been watching this too and feel that it’s going in a direction that contradicts my understanding.

My biggest issue with Input System being built-in package is that there are some VERY POOR design decisions and without being able to fork it, we’re just out of luck.

I’d love to see moving away from string representation everywhere. Bindings are strings, processors and it’s data are strings. Every time you or Input System works with it, there string parsing and concatenation. This seems wrong.

3 Likes

Hi @Neonage @Laicasaane

I want to apologize for the confusion I caused via the Netcode announcement as I used the phrase “built-in package” (which can’t be easily modified) when I actually meant “core package.” (which can be modified). I’ve posted a full clarification over on the original thread explaining it.

Sorry again for the mix-up

7 Likes

Hi @WilsonCWong,

Would you mind sharing the workarounds, fixes and patches you maintain in your fork? Not necessarily the code, though if you want to share that’s great, but I’m interested in the list of things that is not working for you at the moment that requires you to maintain a separate fork, like the UI deselect behavior you mentioned.

Thanks in advance!

2 Likes

Hey @leo-carneiro,

My fork mainly has my hacky deselection behavior fixes, a customized version of the PlayerInput component because of things like this: Please give us an option to prevent PlayerInput from assuming 1 device is 1 player, bug fixes (most of which have been fixed officially throughout the years) and I (poorly) implemented some of the things marked as TODO, FIXME, and REVIEW inside of the package that I ended up needing.

After sleeping on it, I guess it won’t be the end of the world for me to have it as a built-in package because for the first two items, I can write a custom InputSystemUIInputModule and PlayerInput class. The reason for my strong initial reaction to moving it to a built-in package is because I’m aware of severe bugs like this one with polling rate that have existed for over a year, so if something like that can’t get fixed in a timely manner, I doubt any of the small TODO items will even get a look.

I’m honestly just mourning the loss of the power to easily go in and add/fix some of those little items that the Input team didn’t or won’t have time to get to yet, it’s been one of my favorite parts about the move to packages in Unity. It feels like a bit of a step back to close it all off again.

2 Likes

Thanks for the info and context!

I hear you on the power and flexibility that packages gives you, unfortunately its coming at a hidden cost at the moment with the Input System, the Input system is highly coupled with its native parts which is making hard for us to evolve the system and address foundational issues like latency, control connect and disconnects, etc. We can make faster progress by having the Input System being a module that can evolve together with the Native parts.

The goal here is to reduce complexity on the system (right now we need to support multiple editor versions with the same code base) so that we can increase our velocity in order to improve the system faster.

We also believe that the Input System (for better or worse) has a wide public API that allows for extension instead of modification in certain cases and that is also another way to address limitations in the system.

This thread has started conversations internally about this migration, so the decision is not final yet, we are weighing the pros and cons here. Thanks for raising those concerns!

12 Likes