m06 · Transforms · drill · 50 min
Flatten a hierarchy without breaking what it was for
Why this is a drill and not a lab
You measured what depth costs. You know why it costs that. This asks the question neither the reading nor the lab answers: what do you actually do about it, when the deep hierarchy is what the artist authored and you can’t just ask them to stop?
There is no single right answer, which is why there is no walkthrough. There is a right reasoning process, and the constraints exist to force you through it:
| Constraint | The shortcut it closes |
|---|---|
| Authored scene keeps its depth | “Just flatten it in the editor” — solves nothing, and loses the authoring affordance Module 5 says matters |
| Max one level at runtime | Half-measures that reduce depth from 16 to 8 and declare victory |
| No writing LocalToWorld | The tempting fake fix: compute world positions yourself and stamp them in |
| No per-frame ancestor walk | Moving the dependency out of the transform system into your own, which is the same cost wearing a different hat |
| Rigid relations stay rigid | Flattening by simply deleting parents, which is fast, easy, and wrong |
The last two constraints are the interesting pair. Together they say: the relationship must survive, but the per-frame dependency must not. Everything you need to resolve that tension is in Module 5.
How to work it
Milestones, not steps.
- Reproduce the problem. Author or generate a hierarchy at least 8 deep with something identifiable at each level. Confirm in the Entities Hierarchy that the depth is really there, and get a frame-time number with the lab’s probe.
- Decide what is losable. For each level, ask whether anything ever moves that node independently. Levels that exist purely as fixed offsets are candidates for elimination; levels that move are not. Write the answer down before writing code — this is the actual design decision.
- Move the composition offline. The composed offset of a fixed chain is knowable without a player present. Module 5 named the place where knowable things get computed.
- Handle rotation properly. Verify with the rotation check specifically, because translation-only composition passes the position check and fails this one.
- Re-measure. Your ratio should move toward the shallow number. If it didn’t, the dependency is still there somewhere.
When you are done
Answer these without looking at your code:
- Which levels of the original hierarchy did you eliminate, and what property did each of them have that made it safe to eliminate?
- Where does the composition happen now, and what does it cost the player at runtime? (If the answer isn’t “nothing”, say why not.)
- What did you have to do differently for rotation than for position, and what would have gone wrong if you’d treated them the same?
- Your original
depth_penalty_ratioversus the one after flattening — what fraction of the penalty did you actually recover, and where did the rest go? - If a designer now needs one of the eliminated nodes to move at runtime, what breaks, and what is the smallest change that fixes it?
That last question is the real test. A flatten that can’t accommodate a requirement change is a one-way optimization, and knowing exactly which one-way door you walked through is the difference between an engineer and someone who made it faster once.
If you conclude that most of your hierarchy genuinely needs its depth, that is a legitimate outcome and you should record why. A drill that teaches you the optimization doesn’t apply here is not a failed drill.