Bug: spawner clones of traveling move-mode protos misbehave
Observed 2026-06-11 in the nimconf level, while building an alien world
with ~250 units. Enu source referenced in errors: /Users/scott/src/enu.
Summary
Instances created with Proto.new(...) whose script enters move me and
then translates (cruising flyers) exhibit two problems that root units
running the identical script do not:
- They never appear in
units_near (or any unit query), even though
they spawn, draw, and animate — verified visually via screenshot.
- They lose their spawn altitude and end up resting on the ground
(observed with a loop: state-machine behavior; a forever: loop
with an explicit "climb back up" workaround keeps a clone airborne).
Clones that stay put are fine: static protos (trees, tendrils) and
animated-but-stationary protos (a beacon that spins in place via
move me; forever: turn right) appear correctly in units_near —
including one floating at a spawned y = 60 — and hold position.
Repro
Proto (scripts/build_flyer.nim):
name Flyer(tint = red)
let lamp = tint
cylinder(size = 5, height = 1, at = vec3(0, 0, 0), color = black)
cylinder(size = 7, height = 1, at = vec3(0, 1, 0), color = white)
sphere(size = 3, at = vec3(0, 2, 0), color = black)
place(3, 1, 0, lamp)
move me
speed = 12
forever:
turn -40.0 .. 40.0
forward 10 .. 22
Spawner (different script):
drawing = false
Flyer.new(position = vec3(0, 60, 190), tint = red)
Then:
units_near(0, 60, 190, radius = 35) → clone absent (tree clones and
the spawner unit at the same spot are listed). Same result when the
clone is spawned via eval from the spawner's module, and same result
seconds after spawn (not a "wandered away" artifact — tether was 70).
- A screenshot at (0, 60, 190) shows the craft flying there.
- The root self-copy of the same proto (json origin y = 85) is always
listed in units_near at its live, moving position, and holds y = 85
exactly while cruising.
Altitude-loss detail
The original Flyer used a loop: state machine (cruise/hover/go_home,
patterned on .claude/examples/ufo.nim). After a full level load, all 18
fleet clones sat ON THE GROUND (human observation in-world) while the
proto's root self-copy cruised at its json altitude of y = 85. Because
the clones are invisible to unit queries, their y could not be confirmed
programmatically. A rewritten body (forever: + each iteration:
let sag = start_position.y - position.y; if sag > 2.0: up sag) keeps a
clone visibly airborne — i.e. the sag is continuous and fightable, not a
one-time spawn-at-ground.
Possibly related index gap
Clone voxels are invisible to the voxel queries even for clone types
that DO appear in units_near: floor_at(x, z) returns -1 at tree-clone
positions whose trees are visibly present (e.g. an OrbTree clone whose
trunk demonstrably covers its origin column), while proto self-copies'
voxels are found fine. So:
| unit kind |
in units_near |
voxels in floor_at |
holds altitude |
| root unit (any) |
yes |
yes |
yes |
| static clone (tree) |
yes |
NO |
n/a |
| stationary animated clone (beacon) |
yes |
(untested) |
yes (y=60 float) |
| traveling animated clone (flyer) |
NO |
(untested) |
NO |
Speculation: clones aren't registered in the same spatial/unit indexes as
root units, and whatever transform path moving clones use both bypasses
the unit index and re-resolves their vertical position against the
ground.
Workaround used
Traveling units are root units (build_flyer_h1..h5, build_flyer_l1..l5
— one json + script pair each); build_flyer_fleet retired to a no-op.
Works perfectly: queryable, altitude-stable.
Environment
- One MCP session (
enu_mcp), multiple agent bots.
- Both symptoms present before AND after the 2026-06-11 engine bug-fix
restart (the absent-from-queries symptom verified on both; grounding
observed after; pre-restart altitudes unverifiable due to the renderer
backlog at the time).
- Unrelated note for the same backlog:
eval of units_in_box raised
unit sign_… not in node_map [AssertionDefect]
(vmlib/enu/vm_bridge_utils.nim(10,4)) while a sign unit existed.
Bug: spawner clones of traveling move-mode protos misbehave
Observed 2026-06-11 in the
nimconflevel, while building an alien worldwith ~250 units. Enu source referenced in errors:
/Users/scott/src/enu.Summary
Instances created with
Proto.new(...)whose script entersmove meandthen translates (cruising flyers) exhibit two problems that root units
running the identical script do not:
units_near(or any unit query), even thoughthey spawn, draw, and animate — verified visually via screenshot.
(observed with a
loop:state-machine behavior; aforever:loopwith an explicit "climb back up" workaround keeps a clone airborne).
Clones that stay put are fine: static protos (trees, tendrils) and
animated-but-stationary protos (a beacon that spins in place via
move me; forever: turn right) appear correctly inunits_near—including one floating at a spawned y = 60 — and hold position.
Repro
Proto (
scripts/build_flyer.nim):Spawner (different script):
Then:
units_near(0, 60, 190, radius = 35)→ clone absent (tree clones andthe spawner unit at the same spot are listed). Same result when the
clone is spawned via
evalfrom the spawner's module, and same resultseconds after spawn (not a "wandered away" artifact — tether was 70).
listed in
units_nearat its live, moving position, and holds y = 85exactly while cruising.
Altitude-loss detail
The original Flyer used a
loop:state machine (cruise/hover/go_home,patterned on
.claude/examples/ufo.nim). After a full level load, all 18fleet clones sat ON THE GROUND (human observation in-world) while the
proto's root self-copy cruised at its json altitude of y = 85. Because
the clones are invisible to unit queries, their y could not be confirmed
programmatically. A rewritten body (
forever:+ each iteration:let sag = start_position.y - position.y; if sag > 2.0: up sag) keeps aclone visibly airborne — i.e. the sag is continuous and fightable, not a
one-time spawn-at-ground.
Possibly related index gap
Clone voxels are invisible to the voxel queries even for clone types
that DO appear in
units_near:floor_at(x, z)returns -1 at tree-clonepositions whose trees are visibly present (e.g. an OrbTree clone whose
trunk demonstrably covers its origin column), while proto self-copies'
voxels are found fine. So:
units_nearfloor_atSpeculation: clones aren't registered in the same spatial/unit indexes as
root units, and whatever transform path moving clones use both bypasses
the unit index and re-resolves their vertical position against the
ground.
Workaround used
Traveling units are root units (
build_flyer_h1..h5,build_flyer_l1..l5— one json + script pair each);
build_flyer_fleetretired to a no-op.Works perfectly: queryable, altitude-stable.
Environment
enu_mcp), multiple agent bots.restart (the absent-from-queries symptom verified on both; grounding
observed after; pre-restart altitudes unverifiable due to the renderer
backlog at the time).
evalofunits_in_boxraisedunit sign_… not in node_map [AssertionDefect](
vmlib/enu/vm_bridge_utils.nim(10,4)) while a sign unit existed.