UniMate Mesh Preparation
Reading UniMate Mesh Preparation's report
- model
- asset
- report
Every node in this pack is one step of a small pipeline, and this is the step everyone wants to skip and nobody should. UniMate Mesh Preparation is where your mesh stops being a mesh and becomes an asset - a skeleton the model can be conditioned on, with named joints, a known facing direction, and a canonical rest pose. It's also the only node in the pack that needs Blender, it takes about half a minute, and it produces a block of text that tells you whether the next three nodes will work.
Read that text. I mean it. The model is conditioned on the joint labels and the facing pair this step produces, so if the labeller gets either wrong you get a creature animating sideways or backwards and no error anywhere.
What it actually runs
The node shells out to UniMate's own data_process.rig_preprocess:
python -m data_process.rig_preprocess run --input <mesh.glb> --output_dir <cache> \
--no_review --exp_dir <your run> --overwrite
Note the interpreter. That subprocess is UniMate's venv, not ComfyUI's - rig_preprocess needs bpy, which is a ~1 GB wheel pinned to a specific Blender version, and installing that into ComfyUI's environment to prepare a rig once per asset is a terrible trade. The pack resolves the interpreter for you: it uses UniMate's own venv/, or whatever UNIMATE_PYTHON points at. Same pattern as the Blender bridge in ComfyUI-SkinToken.
Output goes to ComfyUI/output/unimate_assets/<name>_<hash>/, holding a cond.npy and the canonical GLB. That hash is a sha1 of the file's contents plus the asset name and the facing overrides. Change the mesh, it re-runs. Re-run the graph, it doesn't - the report says (cached) and the node returns in milliseconds. That's the design: pay once per mesh, iterate freely on the prompt afterwards.
Then it loads cond.npy, counts the joints, compares against the checkpoint's limit, and writes the report.
Inputs and outputs
- rigged_mesh - a forced string input, i.e. wire it from Mesh Loader. You can't type a path here.
- model - the
UNIMATE_MODELhandle from Model Loader; preparation needs the run for its config. - name - optional asset name, defaults to the file stem. Cosmetic, but it's what shows up in the report and the cache folder.
- face_right / face_left - raw bone names of the facing joints. Leave empty to let the offline labeller auto-pick, which it does decently and not perfectly.
- force_rebuild - boolean, wipes the cache folder and redoes the Blender pass.
Out come asset (UNIMATE_ASSET, wire it to both the sampler and the export node) and report, a string.
Reading the report
It looks roughly like this:
Rimuru: 41 joints (built in 27s)
facing pair: r=thigh_R l=thigh_L body_axis=True
labels: hip x2, knee x2, foot x2, ...
Three things to check, in order. The joint count against your checkpoint's limit - 71 on the v3 runs. Over that, the node fails here deliberately, with a message naming the number, rather than letting the sampler refuse silently thirty seconds later. Rig_preprocess will not prune for you, so the fix is deleting finger, face and accessory bones in Blender. That's the trade the pack made and it's the right one: fail loud and early.
The facing pair. r= and l= should be the joints pointing right and left on your creature. If preparation picked a left/right pair off a tail or a wing, the model reads the body as rotated and the whole animation comes out wrong - and there is no error. Override it with the raw bone names in face_right / face_left. Because those values are part of the cache hash, filling them in re-runs preparation automatically; leave one empty and the override is ignored, so fill in both.
The label vocabulary. This is literally what the model is conditioned on - the counts show what the labeller decided each joint is. A quadruped whose front legs got labelled as arms will animate like something that isn't a quadruped.
Traps worth knowing
Blender is only needed here. If rig_preprocess can't start, you get an explicit message about bpy and UNIMATE_PYTHON - point it at any interpreter that can import bpy and you're fine. The export node at the end of the graph deliberately doesn't use Blender at all (UniMate's own mesh-driving path is broken on Blender 4.4+), so you don't need a matching Blender version anywhere else.
Skeleton-only rigs can be sampled but not exported. If your source had no skinned mesh, rig_preprocess writes no canonical GLB, and the export node has nothing to write animation onto. You'll get a perfectly good .npy motion you can't look at. Preparation is the last point where this is cheap to notice.
The cache is content-addressed, so don't fight it. Re-exporting your mesh from Blender changes the file, changes the hash, and re-runs the whole thing - that's correct behaviour, not a bug. force_rebuild is for when you want a clean pass anyway, and it's worth knowing it deletes the folder rather than merging into it.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| rigged_mesh | STRING | — | |
| model | UNIMATE_MODEL | — | |
| nameopt | STRING | Asset name; defaults to the file name. | |
| face_rightopt | STRING | Raw bone name of the RIGHT facing joint (leave empty to auto-pick). | |
| face_leftopt | STRING | Raw bone name of the LEFT facing joint. | |
| force_rebuildopt | BOOLEAN | false | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| asset | UNIMATE_ASSET | — |
| report | STRING | — |