Joël van der Werf
All posts

A street lamp is one thing: scene hierarchy and runtime UI

Parent-child entities and a real UI system, planned against two plain goals and built in two days. The decisions that kept it small.

Two things were missing from Hydro's scenes. Entities couldn't have children: a street lamp's post, light, shadow and flame were four unrelated entities. And the game's menus were rows of sprites pretending to be UI. I wrote one plan for both, with two goals and nothing else in scope:

  1. Hierarchy: move a lamp post in the editor and its light, shadow and flame follow. Save it as a prefab and every instance brings its children.
  2. UI: the inventory, the battle commands and the elder's dialogue are real UI, with text, nine-slice panels and keyboard focus. They stay anchored when the window resizes.

Hierarchy decisions

  • Only a parent link. Each entity stores its parent's ID and nothing else. Children are derived, and the scene's entity order is the tree's depth-first order. The alternative, parent plus first-child plus next-sibling, is three links that must always agree.
  • No dirty flags. World transforms are recomputed for every entity every frame in one linear pass. Scripts write positions directly in many places, so a dirty flag would never be set reliably. I'll add one only if a profiler asks for it.
  • Derived data in its own component. The world transform lives in a separate component that is added and removed with its source, so the pass that computes it never changes the registry while iterating.

UI decisions

  • Unity's model. Rect transforms with anchors, Y up, bottom-left origin: familiar to anyone who has built Unity UI, and well understood.
  • Bitmap fonts first. BMFont files drawn as quads through the existing 2D renderer: no new shaders. A bitmap font generated from any TTF at 32 px is smooth enough at 1×. Signed-distance-field text can come later.
  • Capture is not focus. A visible canvas that blocks gameplay input captures it; focus only says where keyboard navigation goes. Using focus as the signal breaks for a dialogue box with no buttons.
  • One canvas setting for two styles. The test bed uses a 1920 × 1080 reference with smooth fonts; a 480 × 270 integer-scaled pixel UI works too, through the same scale mode setting.
Oxygen hierarchy with nested UI canvases, panels and tabs
The result in the hierarchy: canvases for prompts, the field HUD and the field menu, with panels, tabs and text nested as children.

Tested by rebuilding, not by demos

The plan's test was to rebuild the existing menus as real UI and delete the fake sprite versions. Street lamps and shrine lanterns became prefabs with children. It was built over two days, with every step checked in the editor.

The lesson: write the goal as two sentences, and cut anything that doesn't serve them. The plan stayed small because of it.

Older: Walkable dioramas with Jolt: capsules, ramps and gameplay shapesNewer: From editor to an .exe: the first standalone build

Building a game, an engine, or the tools around them?

I'm based in Tokyo and open to conversations about Unity, C++ and engine roles, C# and .NET software roles, and teams that want to put AI agents to work on real codebases.