the symptom, in your words

"One vmdl, many tagged collision hulls"

✓ verified on 26.08.05
lane Getting art inposted

▸ SYMPTOM

  • You need one collision volume built from several parts, each with its own collision_tags, out of a single vmdl.
  • You are unsure whether a PhysicsShapeList node accepts more than one PhysicsHullFile child.
  • You author a per-child collision_tags value, then a Scene.Trace filter on that tag never matches at runtime.

▸ CAUSE

A PhysicsShapeList node compiles clean with multiple PhysicsHullFile children. Each child reads its own source file and carries its own collision_tags. The engine's own citizen model is the precedent: one PhysicsShapeList holds nineteen shapes.

Compiled across multiple models in one pass, every one reported asset_compile: true and IsCompileFailed: false, with no hints or errors at any level.

The runtime caveat is a separate fact. Authored collision_tags are per-shape data on the compiled model. A scene ModelCollider that consumes that model stamps every shape with the collider GameObject's tags, not the authored per-shape tag (see vmdl-per-shape-collision-tags-inert-on-modelcollider).

▸ FIX

Use PhysicsShapeList to build a compound collision volume from independently-tagged parts in one vmdl. You no longer pick between a single untagged hull and a second hand-authored mesh that a person keeps in sync with the render mesh.

The build regenerates the compound shape automatically. A worked application:

  1. Author the load-bearing geometry as one PhysicsHullFile child with its own tag.
  2. Author a second part render-invisible: give its material no light, so the engine never draws it.
  3. Add that invisible part as its own tagged PhysicsHullFile child beside the first.

The compound shape now blocks a trace or a mover exactly where the invisible part sits, with zero new render draw calls.

For per-shape filtering through Scene.Trace, split the shapes across separate collider GameObjects. A single ModelCollider cannot carry per-shape tags into a trace.

▸ WHY IT WORKS

The per-child tags buy per-shape structure, not per-shape trace filtering. A generator pass can find and drop one specific child by tag at the asset-definition level, and you get a free render and physics split from one source. Runtime tag filtering through a ModelCollider still needs one collider GameObject per tagged shape.

Verified on engine 26.08.05: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?
changelog
  • Published

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