Table of Contents

Class ContentDirectoryStore

Namespace
GrindFest.Content
Assembly
GrindFest.dll

The content-directories provider: registers built content directories, resolves a key to a Unity.Loading.Loadable<T>, and loads it.

This is the same job the Addressables address table does for AssetLibrary, so it lives behind that same door. It is not a second door: AssetLibrary is still the only place the rest of the game asks for an asset.

Facts this type is built on, all measured in this project (2026-09-19, see GrindFest.Workspace/SYNC_LOAD_ELIMINATION_PLAN.md §2.5):

  • Registration reads the build manifest and the root assets into memory (3.7 ms for a small directory; 19.2 ms in a browser) — it is **not** residency. Assets load on Load() (blocking) or LoadAsync().
  • Search order across directories is **reverse registration**, so a mod registered after the base game wins. That is the mod-over-base override, for free.
  • **A build name can be registered only once per session** — registering a second copy of the same name fails — so unregistering has to precede reloading a mod.
  • Unity.Loading.Loadable<T> holds **one** reference: the first Release unloads for everyone. So a caller must not share one; this type keeps the id and hands out a per-caller Loadable.
  • A content directory is built for the **active build target**, and registration requires **play mode** in the editor ("not supported in edit mode").
public static class ContentDirectoryStore
Inheritance
object
ContentDirectoryStore

Properties

AuthoringKeyBuildCount

How many times the authored key set has been (re)built — diagnostics, and a thing tests can assert.

AuthoringOnlyKeyCount

How many keys the authoring source contributes that no built directory has — exactly the set a rebuild of the content directory would add, which makes it the honest measure of "the build is behind the project".

DirectoryCount
HasAuthoringSource

Whether an authoring source (editor) is registered.

IsAvailable

True once at least one directory with roots has been registered, or an authoring source is wired. The editor answers true before any build, which is the point: it is what "content is available" means there. Deliberately does not force the lazy key scan.

KeyCount

How many keys the registered directories and the authoring source can serve between them.

Keys

The keys the registered directories and the authoring source can serve together — for tests, diagnostics and name→address resolution. Order is directories first, then the authoring-only remainder, so a caller that takes the first match keeps preferring what actually ships.

Methods

ClearAuthoringSource()

Forgets the authoring source and its keys (used when the editor leaves play mode or rescans).

IsRegistered(string)

Whether this exact path is one of the registered directories.

KeysFor(string)

The keys one registered directory contributed, or an empty list when it is not registered.

Knows(string)
LoadAsync(string)

The async form — the default for anything that can wait.

RegisterAuthoringKeyProvider(Func<IReadOnlyCollection<string>>)

Registers how the authoring source enumerates its keys. Called lazily — see GrindFest.Content.ContentDirectoryStore.EnsureAuthoringKeys() — because enumeration is only needed to resolve a name to an address, and for diagnostics, while single-key lookups go straight through the resolver.

RegisterAuthoringSource(Func<string, Object>)

Registers the editor's authoring source: a delegate that turns an address into the project's own asset, so keys resolve from the AssetDatabase instead of from a built content directory.

Called from the editor assembly (see Editor/ContentPipeline/ContentAuthoringSource.cs), which is why it takes a delegate rather than calling AssetDatabase itself. Deliberately has no play-mode guard: the key set can be prepared in edit mode by tooling, and only the delegate is exercised in play mode.

Release(string)

Gives the store's handle back. The caller count is AssetLibrary's business.

ReleaseAll()

Unregisters everything, releasing what is open first — order matters or Unity logs.

SetAuthoringKey(string, bool)

Adds or removes one authored key — the increment an import callback makes, so a new prefab is visible to the next lookup without rescanning the project.

SetAuthoringKeys(IEnumerable<string>)

Replaces the authored key set after a full (re)scan. Kept whole-set rather than per-key because that is what the scan produces, and a key set that is half-old and half-new is the one state nobody can reason about.

TryLoad(string, out Object)

Blocking load. Legal on every platform (that is the point of content directories) but it is a frame stall, so it stays reserved for values consumed as data — the same rule the plan states for a synchronous read: the value must be needed as data, and its content must already be inside a registered scope.

TryRegister(string, List<string>)

Registers a built content directory. Returns false (with the reason logged) when it cannot be used, so a caller can decide whether that is fatal instead of getting an exception out of the loading path.

Unregister(string)

Unregisters a directory and forgets its keys. Callers that still hold assets must Release first.