Asset acquisition strategy
- Catalog first. Search the asset library for published, conditioned content that matches the need. Catalog assets load instantly, carry preview/collision/LOD conditioning, and cost nothing to reuse. A close thematic match that needs a material tint or scale change still beats a fresh generation.
- Smart asset packages second. When the need is a coherent set (a themed room, a vehicle with wheels and colliders, a furniture family), apply a canonical smart asset package rather than assembling pieces one by one. Packages apply atomically through the backend service, are idempotent to replay, and stay repairable.
- Generation last. Mint a new asset only when the catalog and packages genuinely lack the concept. Generation spends the player's credits, takes wall-clock time, and produces unconditioned output that may need further passes. When generating, be specific about style, scale, and intended placement so one generation suffices.
Generation is async and best-effort, so never bet a prop on it
Model and audio generation are GPU worker-pool jobs (generation_create_job -> a job that a worker must claim and run; see the asset.model.* and asset.audio.* capabilities, backendKind: "worker_pool"). That corridor can be COLD: if the pool has no worker when the job runs, the job retries its small attempt budget and then terminates failed ("Generating asset failed"). Treat a generation job as a request that MAY not land, not a promise that will:
- Quote or read the dispatch result.
generation_quote_joband thegeneration_create_jobresult carrydispatch.budgetBlockedanddispatch.capacityBlocked. A blocked dispatch means the job will not run; do not sit polling a job that was refused at creation. - Poll for terminal status, do not assume success. After creating a job, read
generation_get_jobuntil it reaches a terminal state. Afailedstatus is a real outcome to handle, not a transient to retry forever. - Have an in-envelope fallback ready BEFORE you generate. When a model job fails or the pool is cold, the always-available routes still ship the build: take a fitting mesh from the CATALOG, COMPOSE the prop from primitive parts as one prefab subtree (see composed-props-from-primitives), or import a
gltf/glb/obj. Image and texture generation via the external synchronous provider (backendKind: "external_sync") does not depend on the GPU pool and is the more reliable generation lane when you only need a texture.
Do NOT leave a textureless billboard RenderableComponent as the "prop" when a mesh generation fails: a billboard with no material renders as a grey quad, not a tree. Fall back to composition or the catalog instead (the create tool teaches this at the boundary).
Signals that the earlier tier was skipped too eagerly: multiple generations of near-identical primitives, generating an asset whose name closely matches a catalog entry, or minting single-use variants of a package the project already applied.
This is advisory strategy, not policy: the kernel never enforces an acquisition order, and a run with explicit user direction ("generate me a fresh one") follows the user.