Class ContentRootAsset
Root asset of a content directory build (Unity 6.5+ "content directories", the engine-level replacement for AssetBundles).
Why this type exists: UnityEditor.BuildPipeline.BuildContentDirectory refuses anything that is not a ScriptableObject — "The RootAsset 'X' is not a ScriptableObject. RootAssets must derive from ScriptableObject." — and only the assets reachable from such a root (directly, or through a Unity.Loading.Loadable<T>) end up in the build. So a root asset is where a name becomes a loadable reference, which is the job the Addressables address table does today.
Relationship to the rest of the content platform: this file replaces resolution (key string →
asset), not the definition layer. ContentDB/defs/*.json keep answering "what is this item",
and a root asset answers "where is its prefab, and is it loadable yet".
One entry type for every kind of content: a Unity.Loading.Loadable<T> built from a
Unity.Loading.LoadableObjectId. Verified 2026-09-19 that a GameObject, a ClipTransitionAsset, a
DropTable and a BuildPlannerPreset all produce a valid id and construct a Loadable — the id
identifies the object, so the type argument does not have to match the asset's concrete type. That matters:
153 of the 3941 content records are not GameObjects (ClipTransitionAsset, TextAsset, Texture2D, FieldSetup,
CharacterClass, RoomShape, DropTable, …).
Unity loads every root asset of a registered content directory into memory, so the entries here must stay small: a key and a Unity.Loading.Loadable<T>, never a direct reference to a heavy asset.
[CreateAssetMenu(fileName = "ContentRootAsset", menuName = "GrindFest/Content/Content Root Asset", order = 0)]
public class ContentRootAsset : ScriptableObject
- Inheritance
-
objectContentRootAsset
Fields
- directoryName
The name this content directory registers under. It must be unique per session — “Failed to register manifest because another manifest with that name was already registered” — and it is also the runtime path segment on Web (
/vfs_streamingassets/<name>), so it is a stable, hand-readable name.
- entries
Every named asset this content directory can serve.
- source
Where this scope came from, for a human reading the asset.
Methods
- TryGet(string, out Loadable<Object>)
Linear lookup. Deliberately not a dictionary yet: the call sites are per-acquire, not per-frame, and a cache would have to be invalidated when a mod registers another directory (a later registration wins, because
ContentLoadManagersearches directories in reverse registration order). Build the index once the call pattern is known.