I asked my Wizard….
’Thomas Kumlehn suggests keeping the property declaration at the local level without a value, then setting values in the variants. This preserves the property definition and allows metadata.
What Thomas is suggesting
Instead of removing the property entirely, declare it without a value:
def Xform “Branch” (
variantSets = [“sizes”] # Declare that this prim has a variant set called “sizes”
variants = {
string sizes = “small” # Set the default variant selection to “small”
}
)
{
#KEY POINT: Declare the property WITHOUT assigning a value
#This creates a property definition but NO Local opinion
#Without a Local opinion, variants (which are weaker than Local but stronger than Payloads)
#can successfully set the value via LIVERPS composition strength
custom double length #Property exists for connections, but variants control the value
variantSet “sizes” = {
“small” {
#Variant “small” sets length to 0.5
#This works because there’s no Local opinion overriding it
custom double length = 0.5
}
“large” {
#Variant “large” sets length to 2.0
#This also works because there’s no Local opinion
custom double length = 2
}
}
}
Why this helps
-
Property exists: The property is declared, so connections like </Branch.length> resolve even when variants aren’t loaded.
-
Metadata: You can attach metadata to the declaration:
custom double length (
doc = “Branch length in meters”
displayName = “Length”
)
- Type safety: The type is defined upfront, which helps tools and validation.
The key difference
This follows LIVRPS: the local declaration doesn’t create a value opinion, so variant opinions can provide the values without conflict.
Should I check your USD_GoodStart repo to see if this pattern is documented, or add it if it’s missing? –> Yes
Also, please explain when to use which approach:
When to Use Thomas’s Approach vs Jan’s Payload Pattern
These are complementary strategies that solve different problems at different architectural levels:
Thomas’s Approach (Property Declaration Technique):
- Use when: Adding variants to existing assets that already have properties
- Use when: Retrofitting variant support to legacy USD files
- Use when: Properties need to exist for connections but values come from variants
- Scope: Property-level technique within an asset
- Example: Artist created
custom double length = 1, now you want variants to control it
Jan’s Approach (Payload-Based Architecture):
- Use when: Designing new assets from scratch
- Use when: Building production-ready, scalable asset libraries
- Use when: Heavy geometry needs lazy loading (CAD, robots, machinery)
- Scope: Asset-level architecture pattern
- Example: Creating a new pump asset with geometry in payload, variants lofted above
Combined Best Practice:
For new assets, use Jan’s payload pattern AND Thomas’s property declaration technique together:
# Asset Root File (minimal, as per Jan's approach)
def Xform "Branch" (
prepend payload = @./Payloads/Branch_payload.usdc@ # Geometry in payload (never Local)
)
{
# Property declared without value (Thomas's approach)
# This allows variants to set values while keeping property available for connections
custom double length # No Local opinion - variants control the value
# Variants lofted above payload (Jan's approach)
variantSet "sizes" = "small" {
"small" {
custom double length = 0.5
}
"large" {
custom double length = 2
}
}
}
Decision Matrix:
| Scenario |
Approach |
Reason |
| New asset with heavy geometry |
Jan’s payload pattern |
Performance, scalability |
| Adding variants to existing asset |
Thomas’s property declaration |
Preserves connections, allows overrides |
| Property needs metadata |
Thomas’s approach |
Metadata requires property declaration |
| Building asset library |
Jan’s payload pattern |
Standard production architecture |
| Legacy asset retrofit |
Thomas’s approach |
Works with existing structure |
| Property must exist for connections |
Thomas’s approach |
Property declaration enables connections |
Key Insight: Jan’s approach prevents the problem (no Local opinions in payloads), while Thomas’s approach solves it when you can’t avoid Local opinions (retrofitting existing assets).
→ it is now ‘living’ here: USD_GoodStart/WIP_Docs/OpenUSD_Best_Practices_Guide (17).md at main · jph2/USD_GoodStart · GitHub ’ 5.7 Best Practices for Variants’