Direct reference asset management is the default way of managing assets at runtime in Unity. Whenever you drag an asset into a sceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary or onto a component through the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary window of the Unity Editor, you create a direct reference to that asset. When you build your application, Unity saves any referenced assets in a separate file associated with the scenes in your project.
In Unity, a direct reference is a serialized link from one object to another. When one object holds a direct reference to another, it creates a dependency on that object. When Unity creates a build of your project, it follows all direct references to make sure that all objects that reference each other are included in the build.
In your C# code, these references are typically held by objects derived from UnityEngine.Object
such as GameObject
, Material
, or MonoBehaviour
.
For example, a GameObjectThe fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary directly references each Component
attached to it, such as a Transform
, MeshRenderer
, or a MonoBehaviour
script, and the Component
holds a direct reference back to its parent GameObject.
You can also use [SerializeReference]
to create references to non-UnityEngine.Object
derived C# objects.
Unity handles object references in different ways depending on if the referenced object is derived from UnityEngine.Object
, or if it’s a C# object referenced with [SerializeReference]
.
If a field references an object derived from UnityEngine.Object
, then Unity doesn’t serialize the entire object’s data, and instead serializes a pointer to that object.
The pointer contains the following information:
UnityEngine.Object
. Every asset file in your Unity project such as .prefab
, .mat
, .png
, .unity
scene files, and .cs
script files have a corresponding .meta
file that stores its GUID.GameObject
instances with their own components. Each of these internal UnityEngine.Object
instances has its own unique fileID
within that single prefab file.Internally, Unity represents these references with a PPtr<T>
type. When Unity loads these objects into memory at runtime, it resolves the GUID and fileID pair to an InstanceID
, which it then uses to track the live object. The InstanceID
is unique to the current Unity Editor session or runtime instance.
If you open a scene file (.unity
) or prefab file (.prefab
) in a text editor, you can check the references to UnityEngine.Object
derived types represented like the following:
# A MonoBehaviour on a GameObject referencing a Prefab asset
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 100100000} # Reference to the GameObject this component is on (internal fileID)
m_Enabled: 1
m_EditorHideFlags: 1
m_Script: {fileID: 11500000, guid: f5ee4a4c1e4c3b448a97448840cdf0f41, type: 3} # Reference to the MonoBehaviour script asset (GUID of script file, fileID 11500000 often for MonoBehaviour)
myTargetPrefab: {fileID: 100100000, guid: 61da4d63ca179b54a97448840cdf0f41, type: 3} # Reference to an external Prefab asset (GUID of Prefab file, fileID 100100000 for the root GameObject within the Prefab)
In this example, myTargetPrefab
points to:
* fileID: 100100000
: The specific referenced object (likely the root GameObject) within the target prefab file.
* guid: 61da4d63ca179b54a97448840cdf0f41
: The GUID of the prefab asset file.
* type: 3
: The type of asset. type: 3
typically means a prefab or script asset.
By default, Unity serializes any objects not derived from UnityEngine.Object
by value. This means that it embeds the entire data of the object directly into the serialized data of the object that holds the reference.
You can use the [SerializeReference]
attribute to change this behavior and instruct Unity to store references to plain c# objects by reference rather than value. This is useful if you want to allow multiple objects to reference the same C# object within a serialized structure and avoid data duplication.
You can’t use [SerializeReference]
to reference a UnityEngine.Object
-derived class. For more information, refer to Serialization rules.
When Unity loads assets and scenes into memory, it uses internal data structures to map references to live objects. These data structures include Ptr
, TypeTree
, Remapper
, and PersistentManager
. For UnityEngine.Object
references, Unity maps the serialized GUID and fileID pairs to live C++ Object*
pointers. For [SerializeReference]
objects, Unity maps internal numeric IDs to live object instances. Finally, Unity maps these C++ pointers to UnityEngine.Object
and plain C# instances that your code can use.
When Unity builds or loads assets, it creates a dependency graph starting from the root object and recursively traverses all direct references. Unity loads the complete graph into memory so the root object functions correctly.
Direct references can impact the build size of your application. If a UnityEngine.Object
asset is directly referenced by any object in your project that makes it into the build, then that asset (and its entire graph of direct dependencies, resolved via GUID
and fileID
pairs) are included. This means careful management of direct references is crucial to prevent unused or unintentionally included assets.
For more information about the files Unity creates when it makes a build, refer to Output of build files.
If you have large lists of assets that you need to share across multiple scenes, or update without modifying scene files, you can use a ScriptableObject
instance to manage this. A ScriptableObject
can hold direct references to other assets, which act as an asset catalog of references to your project’s assets. ScriptableObject
instances are serialized assets and persist across Editor sessions and builds. You can reuse them across multiple different MonoBehaviour instances, and they can help reduce scene file size. For more information, refer to the ScriptableObject documentation.
You can also use AssetDatabase.FindAssets
to find assets and populate a ScriptableObject
with the data.