Set USD Attribute/Primvar
Write real USD data from the graph
- USD
- value
- USD
Attributes and primvars are how USD stores data on a prim that isn't geometry or transform - colors, custom metadata, weights, per-point data a shader reads, anything a renderer or a DCC will want to find later. Set USD Attribute/Primvar is the node that writes them, which makes it one of the pack's more powerful and more confusing tools. Powerful because almost any typed data can be authored; confusing because it's a generic box with a lot of moving parts.
Why you'd reach for it
The pack gives you Set USD Prim Display Color for the one attribute everyone sets (display color) and TransformUSDPrim for transforms. This node is everything else. You want a density float on a mesh for a point-cloud render? A color3f attribute for a custom shader hookup? A token metadata string your downstream tooling greps for? This is the node. It's also the first place you'll want to go when you look at a .usda file, see float density = 1.0, and want to drive that from your graph instead of a text editor.
How it works
Under the hood it resolves your prim_path against the stage - exact paths, single-segment */? wildcards, and recursive ** patterns are all supported - then writes the attribute onto every prim that matches. If is_primvar is on (the default), it creates a primvar (namespaced primvars:name, the USD way to attach per-prim data that's intended for interpolation); off, it creates a plain attribute. The value gets converted into the exact USD type you picked.
The input that trips people up is value. It's a * (any-type) socket, and it's not expecting a bare number or string - it's expecting one of the pack's value payloads, like Create USD Vec3, Create USD Color, Create USD Quaternion, Create USD Token, or Create USD Matrix. Those nodes output a {"data": ..., "type": ...} structure the converter understands. Feed it a raw float and it'll blow up; feed it a Create USD Vec3 and it just works.
The inputs that matter
prim_path- where to write. Default is/Root/Mesh; get it wrong and you get a hard error (No prims matched: ...), not a silent no-op.usd_attribute_name- the attribute name, e.g.densityormyAttribute.usd_attribute_type- a dropdown of 54 USD types: the scalars (bool,float,double,string,token,asset), vectors, colors, quaternions, matrices. Pick the one that matches your value node.is_primvar- on by default. Turn it off for a plain attribute.value- the payload from a Create USD * node.
The output is USD, the same stage with the attribute authored, so you can keep editing or save it.
Install
Same pack, same drill - ComfyUI Manager (search "ComfyUI-OpenUSD") or:
cd ComfyUI/custom_nodes
git clone https://github.com/cjhosken/ComfyUI-OpenUSD
Then restart. The real install cost is usd-core==26.5 (Pixar's USD bindings, chunky), alongside numpy, trimesh, and pygltflib. No model files anywhere in this pack.
Troubleshooting
No prims matched- your path is wrong, or you're guessing. Run the stage throughUSD to Textfirst and look at the actual prim paths.- Value errors / type errors - you wired a plain primitive into
valueinstead of a Create USD * node. The socket wants the pack's structured payload. - The attribute isn't a primvar - check
is_primvar; if you expectedprimvars:namein the.usda, that toggle is how you get it.
Fair warning: this is a brand-new pack (0.1.1, no community track record). The 54-type dropdown is generous, but the array-value path is rougher than the scalar path. Start with scalars and Create USD Vec3 before reaching for the exotic types.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| USD | USD | — | |
| prim_path | STRING | /Root/Mesh | — |
| usd_attribute_name | STRING | myAttribute | — |
| usd_attribute_type | COMBO | vector3f | 54 options: asset, bool, color3d, color3f, color3h, color4d, +48 |
| is_primvar | BOOLEAN | true | — |
| value | * | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| USD | USD | — |