"s&box won't load my OBJ/GLB"
- Dropping an
.obj/.glbintoAssets/does nothing useful in a scene. Model.Load("models/foo.obj")fails or never resolves as a usable model.- The
.vmdlcompiles but materials error with something like:unable to resolve X.vmat. - Model shows untextured / ERROR after a scripted re-export.
s&box does not load raw OBJ/GLB in scenes. The engine compiles a .vmdl wrapper on load. The mesh file is only a RenderMeshFile (and optionally physics) input referenced by that wrapper.
Material remaps must map both names — "MatName" and "MatName.vmat" — in the DefaultMaterialGroup remaps, or the compiler errors with unable to resolve X.vmat. A MaterialOverride on the renderer is not a substitute.
Related trap: Blender's OBJ exporter with export_materials=False silently drops the usemtl line too (not just the .mtl file). Remaps key off that material-group name, so the mesh compiles untextured.
- Put the mesh under
Assets/models/<your-project>/foo.obj(and.mtlif needed). - Emit a sibling
foo.vmdlthat references it.
Minimal wrapper shape (KV3 text — copy structure from any working hand-authored vmdl in your install):
<!-- kv3 encoding:text:version{...} format:modeldoc29:version{...} -->
{
rootNode =
{
_class = "RootNode"
children =
[
{
_class = "MaterialGroupList"
children =
[
{
_class = "DefaultMaterialGroup"
remaps =
[
{ from = "MatName" to = "materials/your/mat.vmat" },
{ from = "MatName.vmat" to = "materials/your/mat.vmat" },
]
},
]
},
{
_class = "RenderMeshList"
children =
[
{
_class = "RenderMeshFile"
filename = "models/your-project/foo.obj"
import_scale = 39.37
import_rotation = [ 0, 0, 0 ]
// translation origin as needed
},
]
},
]
}
}Exact header GUIDs: copy line 1 from a known-good hand-authored .vmdl (citizen addon or your own pipeline output) — do not invent format versions. See also the modeldoc32 trap in ai-generated-models.
After any scripted OBJ export, grep the output for usemtl and vt . If usemtl is missing, re-inject usemtl <name> before the first f line rather than re-enabling material export (which can write a stray .mtl into a delivery folder you don't want).
Load in code with a root-relative vmdl path, forward slashes, no Assets/ prefix:
var model = Model.Load("models/your-project/foo.vmdl");Kick the editor if a new vmdl doesn't show (hot-compile on focus).
ModelDoc is the compile unit. OBJ/GLB are mesh sources; without a vmdl there is nothing for the resource system to compile into a Model. Remap keys must match whatever string the mesh importer emits for the material slot — some paths emit the bare name, some append .vmat — so mapping both closes the gap. MaterialOverride only swaps at runtime on an already-resolved material group; it cannot fix a failed compile-time remap.