Log inGet started

dynamicAsset (asset type)

A prompt-driven, self-regenerating 3D asset. A <name>.dynamicAsset/ folder holds a text prompt.json; the asset's model is generated from that prompt by the @builtin::services.meshy text-to-3D…

This type is the reference example for the asset-type onChange change-callback (the type-level analogue of a component's onAssetReload). Read its behavior.luau to see the pattern end to end.

Folder shape

<name>.dynamicAsset/
├── prompt.json        { "prompt": "a mossy stone golem" }
├── .metadata          generation status + start date + last prompt
├── README.md
├── model/             (after first generation)
│   ├── model.glb       the current generated mesh
│   └── model.json      manifest (prompt, date, service handle)
└── versions/          (after the prompt changes at least once)
    ├── v1/
    │   ├── model/model.glb
    │   ├── prompt.json  the prompt that produced this version
    │   └── meta.json
    └── v2/ …

Lifecycle

  1. Generateref:generate("a mossy stone golem") writes the prompt, sets .metadata.generationStatus = "inflight" + generationStartedAt, and launches Meshy. The GLB is written straight into model/.
  2. Statusref:status() reads the state from .metadata: status (empty/inflight/succeeded/failed), stage (live Meshy stage), prompt, startedAt, finishedAt, error, handle. Use it to find finished / failed / in-flight assets at a glance.
  3. Edit the prompt → regenerate — writing prompt.json (by hand, vfs.write, ref:setPrompt(...), or a pull) fires onChange. If the prompt actually changed, the current model/ is archived into versions/v<N>/ (incrementing) and a fresh generation starts.

Methods (AssetRef<dynamicAsset>)

MethodWhat it does
:generate(prompt?)Generate/regenerate now (async). Returns the status table.
:status()Read generation status from .metadata.
:getPrompt() / :setPrompt(text)Read / set prompt.json (set triggers regeneration).
:modelPath()VFS path of the current GLB, or nil.
:versions()Archived version indices (oldest first).
:spawn(name?, x?, y?, z?)Spawn the current model into the scene.

Setup

The Meshy service reads its key from the MESHY_API_KEY environment variable (set before launching the engine). Without it, generation fails with a clear message and :status().status == "failed". Get a key at https://www.meshy.ai/api.

Usage

asset.create("dynamicAsset", "Golem")
local golem = asset.resolve("Golem", "dynamicAsset")
golem:generate("a mossy stone golem, low-poly")
-- … wait …
print(golem:status().status)        -- "succeeded"
golem:spawn("golem", 0, 0, 0)

-- Change the prompt → archives v1, regenerates:
golem:setPrompt("a bronze golem, ornate")
print(golem:versions())             -- { 1 }

Notes

  • Generation is async and can take minutes. onChange returns immediately; the model appears when :status().status flips to "succeeded".
  • onChange is convergent: it only acts when the prompt differs from the last generated prompt and queues edits made mid-generation (pendingPrompt), so it never loops on its own writes.
  • asset-type
  • reference