Packages must follow Semantic Versioning (SemVer). Semantic Versioning is a strategy that allows package authors to provide information on the type of changes included in a given version, compared to the previous version, in a format that automated tools can use.
Semantic Versioning expresses versions as MAJOR.MINOR.PATCH, where MAJOR introduces one or more breaking changes, MINOR introduces one or more backward-compatible API changes, and PATCH only introduces bug fixes with no API changes at all.
When you begin to develop a package, start the version number at
0.1.0. The MAJOR version number
0 is reserved for packages in their initial development phase. During initial development, package APIs change often, frequently in a breaking manner, so keep the MAJOR version number at
0 until you consider your package stable enough and ready for use in production.
After a package is officially ready for use in production, increment the MAJOR version to
1 and adhere to the following guidelines for subsequent changes:
|Increment this value:||Under these conditions:||Example:|
|MAJOR||There is at least one breaking change and neither version of the package can be substituted for the other. A breaking change includes:
• Changing the API surface (the exposed part of the API) or features in a way that risks compilation or runtime errors.
• Removing non-API features, including removing Assets or changing an Asset’s GUID.
• Removing or renaming assemblies and Assets (because) the compiler might fail to locate them).
Note: When incrementing the major version, always reset the PATCH and MINOR values to
|Versions 1.2.3 and 2.0.0 are not compatible and cannot be used interchangeably without risk.|
(same MAJOR value)
|The highest MINOR introduces functionality in a backward-compatible way. A backward-compatible (or non-breaking) API change includes:
• Changing the API surface or features without risking compilation or runtime errors.
• Adding non-API features.
• Adding assemblies and Assets (because new items don’t have pre-existing references).
Note: When incrementing the minor version, always reset the PATCH version to
|You can use Version 1.3.0 to fulfill a dependency on 1.2.0, because 1.3.0 is backward-compatible.
You can’t use 1.2.0 to fulfill a dependency on 1.3.0.
(same MAJOR.MINOR values)
|The highest PATCH introduces bug fixes without changing the API at all, in a backward-compatible way. The API doesn’t change if:
• The API surface is identical and the features remain unchanged.
• The changes don’t alter the public API.
|Versions 1.3.0 and 1.3.1 should be interchangeable because they have the same API, even though 1.3.1 contains a bug fix not present in 1.3.0.|
Following these versioning practices allows the Package Manager to automatically solve conflicts (when possible), or upgrade packages to newer, backward-compatible versions.
The following sections describe scenarios to help you determine how these rules affect various package elements:
In addition to these scenarios, there is another factor that can affect some changes that would normally require only a MINOR or PATCH version increase: whether the Auto Referenced property is enabled or disabled.
One of the properties you can set for your assembly definitions is the Auto Referenced property, which controls whether Unity automatically references the file during compilation. When this property is enabled, some changes that would normally require only a MINOR or PATCH version increase now become breaking changes.
When you disable auto-referencing, if you make any change that results in a new assembly being available, you are introducing a backward-compatible change to the API. Backward-compatible API changes, such as adding platforms, disabling Unity Test References, adding a new .asmdef, or removing Define Constraints, only require a MINOR increase.
However, when you enable auto-referencing, that newly-added assembly is implicitly added to the references of various other assemblies. Since those cases can lead to compilation errors in those other assemblies, so it requires a MAJOR increase.
Another common case occurs when you add or change versions for a package dependency. Most of the time, changing the package dependency only requires a PATCH increase. However, the new package version might contain an assembly with the Auto Referenced property enabled, which becomes a breaking change, and therefore requires a MAJOR increase.
To avoid problems like these, always try to avoid putting a third-party DLL file into an unrelated package (such as including Newtonsoft.Json.dll in a SaveGameManager package).
A project can reference any asset that is visible to the Asset Database. The Asset Database tracks these assets uniquely using the GUIDs defined in their .meta files.
When you introduce one of these changes to the public API, this requires a new MAJOR release, because they are breaking changes:
|Scenario:||Why these are breaking changes:|
|Removing an Asset that is visible to the Asset Database||If you remove an Asset, this might break references in user Projects or other packages.|
|Changing the GUID of an Asset||If you change an Asset GUID, the Asset Database understands this as removing the original Asset and then adding a new (identical) Asset. This results in a broken reference, because the original GUID no longer points to the Asset, so the Asset Database cannot resolve the reference.|
Assembly definitions (.asmdef) define a group of scriptsA piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary which the Unity Editor’s compilation pipeline turns into separate managed assemblies (.dll). These .asmdef assets include properties that drive the resulting assembly’s properties. This includes:
Most properties have an impact on the consumers of the assembly, so changing any of these properties constitutes a change to the package’s public API. Other properties have no impact on the consumers of the assembly, so changing any of these is not considered changing the package API.
Warning: The Auto Referenced property is a special case, because many of the changes that would normally not change the API at all or would change the API in a backward-compatible way could cause compilation errors, depending on whether or not it is enabled. For more information, see Automatic referencing.
Unity can either pre-compile assemblies, or compile them from scripts and an assembly definition. Therefore, anything that applies to assembly definitions generally also applies to precompiled assemblies.
This section details changes in assembly definitions and precompiled assemblies, and the impact on the package version:
When you introduce a breaking change to the public API, this requires a new MAJOR release, because it might cause compilation and runtime errors. These scenarios all remove or hide an assembly from any other assemblies that reference it. When an assembly using a type defined in a referenced assembly is compiled, if the compiler cannot find that other assembly, that results in compilation errors. For more information about working with assemblies and assembly definitions, see Assembly Definitions.
Note that the following applies to both run-time and Editor assemblies that packages consume and use. It doesn’t apply to test assemblies, because packages do not normally consume them, so they are not part of a package’s API.
|Scenario:||Why the compiler can’t find the referenced assembly:|
|Removing an assembly definition or a precompiled assembly||Removing an assembly definition file prevents the compilation pipeline from generating the corresponding assembly.
Note: As of 2019.1, missing references are allowed to support the “optional reference” use case, but renaming an assembly that Unity needs to compile an assembly definition causes compilation errors. Likewise, if compiled code needs a type from an assembly, renaming that assembly can result in run-time errors such as
|Changing an assembly name (either in the .asmdef file or renaming the .dll file)||Changing the assembly name is equivalent to removing the assembly and then adding a new one with a different name. This means Unity considers the original assembly to be missing, even though the API still contains the same assembly code under another name.|
|Adding a define constraint to an .asmdef||If you add a define constraint, Unity skips compiling the assembly whenever the define constraint is not met. This creates cases where the assembly is missing, even though it was previously available.|
|Removing platforms||If you remove support for a specific platform, Unity no longer imports the assembly on that platform, which is equivalent to removing the assembly.
You can remove a platform by enabling one of these properties:
• includePlatforms, which breaks compatibility with all unlisted platforms
• excludePlatforms, which adds entries to it
|Moving public APIs from one assembly to another||When you move publicly accessible code from Assembly A to Assembly B, any assembly that references A but not B fails to compile.
For assembly definitions, if you move scripts around, you might be moving public APIs to a different assembly.
|Changing the Auto Referenced property||When you disable the Auto Referenced property, you can no longer use the public API of this assembly without an explicit reference:
• For precompiled assemblies, disabling this property prevents Unity from implicitly adding the precompiled assembly as a reference to assembly definitions and project-compiled assemblies.
• For assembly definitions, disabling this property prevents Unity from implicitly adding the resulting assembly as a reference to project-compiled assemblies.
When you enable the Auto Referenced property, it potentially introduces conflicts with other changes to the API, properties, or dependencies. For more information, see the Automatic referencing section.
|Enabling the Unity References → Test Assemblies property in assembly definitions||Enabling the Unity References → Test Assemblies property marks this assembly as a test assembly, and Unity doesn’t normally include it in builds (or compile it in some cases). When this happens, any assembly referencing the missing assembly fails to locate it, unless it is also a test assembly.|
The following changes are backward-compatible, or non-breaking, API changes. These scenarios all add an assembly, unlike breaking changes which remove an assembly. Since adding an assembly increases the API surface (the exposed part of the API), it is considered an API change. However, there are no existing references, so adding a new assembly won’t affect other assemblies created with an earlier API.
Backward-compatible changes require at least a new MINOR release. If you are including other updates that are breaking changes, then these can also be part of the new MAJOR release.
Warning: These changes are only backward-compatible if the Auto Referenced property is disabled. When the Auto Referenced property is enabled, the changes listed in this table might result in breaking changes. For more information, see the Automatic referencing section.
|Scenario||Why these changes don’t break compilation|
|Removing a define constraint to an .asmdef||Removing a define constraint means that the compilation and scripting pipelines no longer skip this assembly. Because Unity always builds that assembly, the compiler can always resolve references to it, regardless of whether or not that define constraint is met.|
|Adding platforms||Adding platforms has no effect on existing platform support, so it is backwards-compatible. This is an API change because it increases the API surface.
You can add platforms by modifying these properties:
• Add entries to the includePlatforms property.
• Remove the includePlatforms property completely. This is equivalent to adding all platforms that were not already in the includePlatforms property.
• Remove entries from the excludePlatforms property.
|Creating an assembly definition with new scripts (not previously under a different .asmdef file)||A|