Table of Contents

Class ContentRootAsset

Namespace
GrindFest.Content
Assembly
GrindFest.dll

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
object
ContentRootAsset

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 ContentLoadManager searches directories in reverse registration order). Build the index once the call pattern is known.