Skip to content

How Checks Decide

m4bwav edited this page Oct 12, 2026 · 1 revision

pw.py check FILE --target T inspects the file and compares it with the rules of one target. The rules live in skills/polywright/references/targets.json, each target with advice lines that say where its numbers come from (checked 2026-10-11).

python pw.py check --list
{
 "targets": {
  "game-roblox": "Roblox MeshPart through the 3D Importer (FBX, OBJ or glTF)",
  "game-unity": "Unity prop or character (GLB through glTFast or FBX)",
  "game-unreal": "Unreal Engine 5 static mesh (FBX, glTF or USD)",
  "web-threejs": "three.js, model-viewer or Babylon page (GLB)",
  "ar-usdz": "Apple AR Quick Look (USDZ)",
  "commerce-gltf": "Product model for e-commerce viewers (Khronos 3D Commerce guidelines)",
  "print-fdm": "FDM print, 0.4 mm nozzle, 256 mm cube bed (Bambu P1S, X1, A1 class)",
  "print-resin": "Resin (MSLA) print: miniatures and fine detail",
  "video-blockout": "Blockout or proxy for AI video and previs (structure guides, depth and normal passes)",
  "cad-step": "Engineering interchange (STEP from code CAD), with a mesh preview"
 },
 "checked": "2026-10-11"
}

Exit code 0.

Rules

Rule Fails or warns when Targets that use it
max_tris the file has more triangles than the limit (game-roblox and the advisory budgets warn; others fail) roblox, unity, web, ar, print, video
max_tris_per_object one object is over the limit roblox (20,000)
max_objects more objects than the limit (warn) none by default
max_materials more materials than the limit (warn) roblox (1), unity (4)
max_image_px the largest texture side is over the limit (warn) roblox 1024, web and ar 2048, unity 4096, unreal 8192, commerce 2048
require_uvs an object has no UV map roblox, unity, unreal, web, ar, commerce
require_watertight there are boundary or non-manifold edges print-fdm, print-resin, cad-step
single_part more than one separate part (warn) print-fdm
forbid_unapplied_scale an object still has a scale other than 1 (warn) roblox, unity, unreal, commerce
max_dims the size does not fit the box in any rotation print-fdm (256 mm cube), print-resin
min_feature never measured: reported as unchecked, look at a render print-fdm 0.9 mm, print-resin 0.3 mm
max_file_mb the file is bigger than the limit (warn) web 10, ar 25, commerce 5
real_scale with --real-size-m X: the longest side is more than 10%% off X any

The status is fail when any rule fails, warn when any warns, pass otherwise; the exit code is 1 only for fail. ok is false only on fail.

Reading a result

The park scene from Commands against Roblox: under the triangle limits and the right size, but six materials (Roblox takes one per mesh: a warning) and no UVs (a failure):

{
 "ok": false,
 "target": "game-roblox",
 "status": "fail",
 "results": [
  {
   "rule": "max_tris",
   "status": "pass",
   "detail": "6196 tris (limit 20000)"
  },
  {
   "rule": "max_tris_per_object",
   "status": "pass",
   "detail": "ground_park has 4312 tris (limit 20000)"
  },
  {
   "rule": "max_materials",
   "status": "warn",
   "detail": "6 materials (limit 1)"
  },
  {
   "rule": "max_image_px",
   "status": "pass",
   "detail": "largest texture 0 px (limit 1024)"
  },
  {
   "rule": "require_uvs",
   "status": "fail",
   "detail": "objects without UVs: ground_park, ground_default, roads, buildings, trees, tree_trunks"
  },
  {
   "rule": "real_scale",
   "status": "pass",
   "detail": "longest side 111 m vs expected 110 m (x1.01)"
  }
 ],
 "advice": [
  "20,000 triangles per mesh (create.roblox.com specifications, checked 2026-10-11; vendors quote 21,000, test the importer). Split bigger models into several MeshParts.",
  "One material per mesh; SurfaceAppearance takes colour, normal (OpenGL, Y+), roughness, metalness. Texture size limit unverified (historically 1024 px).",
  "1 stud = 0.28 m: a 1.8 m person is about 6.4 studs. Export in metres and scale in Studio, or scale by 1/0.28 before export.",
  "At most 4 bone influences per vertex, root joint at the origin, no zero-thickness surfaces. CollisionFidelity Box or Hull for props."
 ],
 "inspect": {
  "tris": 6196,
  "objects": 6,
  "dims": [
   111.01131,
   111.03461,
   7.3
  ],
  "watertight": false,
  "parts": 6,
  "materials": [
   "buildings",
   "ground_default",
   "ground_park",
   "roads",
   "tree_trunks",
   "trees"
  ],
  "max_image_px": 0,
  "backend": "blender",
  "blender": "5.2.1 LTS"
 }
}

Exit code 1.

Fix by finishing for the target (Commands: --join --uv), or split the scene into one MeshPart per material. A generated fountain went from this failure to pass after convert --size-m 1.0 --ground --center --max-tris 15000 --uv (2026-10-11).

Where the numbers come from

Target Key number Source (checked 2026-10-11)
game-roblox 20,000 triangles per mesh, one material Roblox's specifications page; vendors quote 21,000
game-unity 50,000 triangles (warn) a project choice for desktop hero props, not a Unity limit
game-unreal no triangle limit Nanite takes dense opaque meshes (UE 5.8 docs)
web-threejs 150,000 triangles, 10 MB (warn) a page-weight choice, not a spec
ar-usdz about 100,000 polygons, 2048 px textures Apple's guidance (secondary source, 2021)
commerce-gltf 5 MB, 2048 px the Khronos 3D Commerce v1.0 figures (the current text gives none)
print-fdm 0.9 mm walls, 256 mm bed two perimeters at 0.4 mm (Prusa); the Bambu P1S class bed

Clone this wiki locally