When you add a package to a project manifestEach Unity project has a project manifest, which acts as an entry point for the Package Manager. This file must be available in the
<project>/Packages directory. The Package Manager uses it to configure many things, including a list of dependencies for that project, as well as any package repository to query for packages. More info
See in Glossary, Unity considers that package a dependency of the project (a direct dependency). However, a package can also have dependencies on other packages, which create indirect dependenciesAn indirect, or transitive dependency occurs when your project requests a package which itself “depends on” another package. For example, if your project depends on the
firstname.lastname@example.org package which in turn depends on the
email@example.com package, then your project has an direct dependency on Alembic and an indirect dependency on Timeline. More info
See in Glossary in any projects that require that package.
Since most projects require more than one package in order to develop games and apps, the Package Manager has to evaluate all the requested package versions to retrieve from the registry (whether direct or indirect), and decide which among those package versions to install. To do this, it computes the set of packages that satisfies all direct and indirect dependencies in the project, starting with the project dependencies and recursively exploring each indirect dependency, collecting all the dependency information, then picking a set of packages that satisfies the dependency requirements without any conflict. For example, this dependency graph represents a project with four direct dependenciesA direct dependency occurs when your project “requests” a specific package version. To create a direct dependency, you add that package and version to the dependencies property in your project manifest (expressed in the form
package_name@package_version). More info
See in Glossary and all of their indirect dependencies:
In this example:
Note: Only package dependencies declared with versions need to be resolved. The Package Manager selects packages installed from other sources, such as embedded packages
See in Glossary, and dependencies declared with local paths, Git URLs, and built-in packages over version-based dependencies.
Depending on the set of packages defined in the project manifest, it could take a long time to evaluate all possible package combinations: a project could potentially depend on hundreds of packages, each of which depend on hundreds of other packages, most requiring different versions.
To provide the most efficient solution, the Package Manager prioritizes package versions that it previously used by tracking them in a lock file. This guarantees that subsequent dependency resolution using the same inputs results in the same outputs. It also minimizes time-consuming operations such as downloading, extracting, or copying packages.
Sometimes, the Package Manager cannot find a solution that only includes locked packages. In this case, the Package Manager uses the solution with the least risky upgrades, preferring patch upgrades over minor or major upgrades, and minor upgrades over major upgrades by default. However, you can customize how aggressive you want the Package Manager to be when considering a higher version with the resolutionStrategy property.
In this example, there are multiple versions of the following packages requested:
firstname.lastname@example.org (twice) and
email@example.com (twice) and
Using the set of direct and indirect dependencies, the Package Manager selects the highest version of the burst package (
firstname.lastname@example.org), which satisfies the
email@example.com package’s dependency: