the symptom, in your words

"Using AI-generated 3D models in a real s&box game"

✓ verified on 26.07.08e
lane Getting art inposted updated

▸ SYMPTOM

You pull an AI-generated (Tripo / Meshy / Rodin-style) asset into Assets/ and get one or more of:

  • Floating ERROR mesh text in-editor.
  • Console: No valid format conversion from 'modeldoc32' to 'modeldoc30'.
  • Material compile FAIL / Unable to read file .../assets/<slug>_color.png.
  • Model loads but is knee-high (everything normalized to ~1 m).
  • Players walk through it (no collider shipped).

▸ CAUSE

Texture-native generators (Tripo, Meshy, Rodin, and similar) can emit mesh + albedo together, wrapped as OBJ + .vmdl + .vmat. That path is real and shippable, but several delivery bugs break the happy path:

  1. format:modeldoc32 header: current engine can't convert to modeldoc30.
  2. Meshes arrive normalized to ~1 m max dimension: no real-world scale.
  3. Corrupt white.png: bad IDAT checksum → texture compile FAIL.
  4. Bare <slug>_color.png in the vmat: material compiler resolves against the Assets root, not the vmat's folder.
  5. No ModelCollider / physics: render-only delivery.

▸ FIX

What you should get (happy path)

snippet
Assets/
  models/ai/<slug>.obj
  models/ai/<slug>.vmdl
  materials/ai/<slug>_mat.vmat
  materials/ai/<slug>_color.png

Reference root-relative, no Assets/ prefix:

snippet
var model = Model.Load("models/ai/<slug>.vmdl");

Conventions when healthy: import_scale 39.37, import_rotation [0,0,0], material remaps for both "name" and "name.vmat", grounded at z=0, triangulated. Geometry face budget often ~8–12k tris.

Bug fixes (per asset until your generator's output is fixed)

1. modeldoc32 header: replace line 1 of the vmdl with the modeldoc29 header from any working hand-authored vmdl (copy line 1 verbatim). Node classes inside are compatible as-is. Error string:

snippet
No valid format conversion from 'modeldoc32' to 'modeldoc30'

2. Scale. Until intended sizes are baked:

snippet
float M = 39.37f;
go.WorldScale = desiredHeightMeters * M / model.Bounds.Size.z;

Prefer baking into a wrapper import_scale at unit WorldScale when you need ModelCollider to match. See scaled-collider-didnt-scale. Remember "normalized ~1 m" ≠ exactly 1 m.

3. Corrupt white.png: re-encode or replace with any clean white PNG.

4. Bare texture path. Edit the vmat TextureColor to the full root-relative path:

snippet
materials/ai/<slug>_color.png

5. Colliders: add a bounds-derived BoxCollider (standard practice). Do not assume ModelCollider works on render-only vmdls (model-no-collision).

Facing

Verified: AI-generated meshes often face the opposite way from the Blender-pipeline convention. Use facing yaw = atan2(dir.y, dir.x)° − 90 (not + 90). Verify one instance.

Characters

Delivered as static meshes (no skeleton). Rig from a copy outside the delivery folder: re-runs overwrite in place. See rigging-ai-generated-mesh.

Hygiene

Don't hand-edit files under a regenerating delivery tree long-term: fork/copy out; a re-run overwrites in place. Each generation costs real money; batch thoughtfully. Exact generator CLI / token layout varies by your tooling. Keep API tokens and other secrets out of public repos.

▸ WHY IT WORKS

The engine path is the same as hand-authored art: ModelDoc compiles OBJ + materials into a Model. The AI farm just has to emit compatible headers, root-relative texture paths, and honest scale. Each listed bug is a packaging mismatch (format version, path resolution, missing physics graph), not a fundamental "AI meshes can't work in s&box" limitation.

Verified on engine 26.07.08e: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Verified against source: removed stale needs-verification hedge on delivery-tree hygiene.

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord