Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


Reference content in a content directory

Use loadable references to include assets in a content build.
Read time 5 minutesLast updated 21 days ago

The references between objects in your project determine which assets Unity includes in a content directory build. You can use the following tracked references to reference content in
ScriptableObject
root assets
:
  • A loadable reference to load on demand at runtime.
  • A loadable scene reference to load scenes at runtime.
  • A direct reference, which is always included in the content directory. However, Unity loads any direct references from a root asset entirely into memory, so it's best practice to avoid direct references to large assets, and aim to use
    Loadable
    references for all assets.
You don't need to reference every asset from a root asset directly. If Unity reaches an object that has a tracked reference of its own, then Unity includes the referenced asset and continues the search from there.
When you build a content directory, Unity starts at the root assets you pass to
BuildPipeline.BuildContentDirectory
and recursively follows every tracked reference it finds. Unity includes every asset it reaches this way in the build output.
An untracked reference is a runtime dependency that isn't visible in the serialized data, so Unity can't follow it at build time. Make sure the content it resolves to is reachable from a root asset in a content directory build.

Loadable references

You can use
Loadable<T>
on classes derived from MonoBehaviour or ScriptableObject to establish on-demand references from one object to another. A loadable reference means that the referenced object doesn't need to be loaded immediately, but it's automatically included in the build output.
The
Loadable<T>
class contains a
LoadableObjectId
that references another object based on where the referenced object is serialized in the source project.
Loadable<T>
is how you split content according to its loading and unloading requirements. Unity loads a direct reference together with the object that holds it, but loads a
Loadable<T>
reference only when your code calls
Load
or
LoadAsync
, and unloads it when your code calls
Release
.

Determine which loadable reference type to use

A serialized field can hold either a
Loadable<T>
or the
LoadableObjectId
inside it. Two things decide which to use: whether you know the type of the referenced object, and whether one object or many will load it.
Store a
Loadable<T>
when you know the type. The field then documents what it holds, and the
Inspector

?

window accepts only an object of that type, so a wrong assignment surfaces while you edit the asset rather than when your code runs. Use a narrower type argument when a field holds one kind of asset, as in Track assets of a single type.
Store a
LoadableObjectId
when the object can be of any type, and let each caller construct a
Loadable<T>
from it for the type that caller expects. Use
Loadable<UnityEngine.Object>
to accept any Unity object.
Whichever you store, anything that loads an asset needs a
Loadable<T>
of its own, because each instance holds at most one reference and Unity unloads the asset when the last instance releases its reference. Sharing a single instance is fine when one object owns the loading, and that object can then call
Load
and
Release
on the field directly. When several independent callers use the same asset, give each one its own instance, either by storing a
LoadableObjectId
, or by returning a new
Loadable<T>
built from the stored one's
LoadableObjectId
. Handing the same instance to several callers means the first
Release
unloads the asset for all of them.

Loadable scene references

LoadableSceneId
is similar to
LoadableObjectId
, but you can use it to reference a scene to bring scenes into a build and load them. There's no direct reference type for pointing to a scene, and you must load scenes on-demand through calls to the
SceneManager
API. For more information, refer to Include scenes in a content build.

Direct references

Direct references are the most common type of reference used in Unity.
An example of a direct reference is the link between a GameObject and one of its components. Objects with direct references between them are usually placed in the same serialized file, because they all need to be loaded together.
For more information, refer to Direct reference asset management.

Untracked references

Tracked references are direct references,
Loadable<T>
, or
LoadableSceneId
fields on a ScriptableObject, MonoBehaviour, or other serialized objects. When Unity builds a content directory, it follows those fields and includes the referenced assets automatically.
An untracked reference is when your application depends on content at runtime, but nothing in the serialized data tells the build pipeline about that dependency. Instead, your code finds the content later, for example by calling
ContentLoadManager.GetRootAssets<T>
and reading fields on the root asset it finds.
You can use untracked references when you want to split content across content directories to create a small Player with bootstrap code that discovers root assets at runtime.
To make untracked references work in your project, do the following:
  • Add the root asset
    ScriptableObject
    to
    rootAssetPaths
    when you run
    BuildPipeline.BuildContentDirectory
    .
  • Register that content directory at runtime before your lookup code runs.
  • Keep root asset types and field layouts consistent between Player and content builds.

When to avoid untracked references

Avoid untracked references for simple single build projects where every dependency can be a direct or
Loadable
reference on objects in the Player or bootstrap scene.
Using untracked references means that it's easier to miss a dependency. For example, the Unity Editor can still use project assets if you forget to build or register the content directory, while a Player build fails until the content directory is built, shipped, and registered. In the AssetBundle system, this functionality is similar to loading by address or AssetBundle name in code without assigning the asset in the Inspector.

Additional resources