The performance panel showed Physics and Editor as the large parts of
a frame in a scene of 222 entities. Nearly all of it came from a
tilemap that only stands there.
- Whoever writes cells in place now says so with cellsChanged. Only
then does cellsVersion compare the content. The comparison ran about
60 times per frame and was the largest single item at 14 percent.
- The four writers call it: the painter during and at the end of a
stroke, PaintTilesCommand on execute and on undo. A new writer that
forgets it stays invisible.
- The game view is drawn once per frame in play. With an animated tile
in view it was drawn twice, once by the run and once by animate().
animate() now gets the redraw count from the start of the tick.
- TilemapField builds the geometry of a mesh only when its source
changes: the cells, the tile size, the origin or the image. For that
groupByTile and layerRows return the same objects for the same list.
- PhysicsSystem skips a tilemap whose source and switch are unchanged.
The switch is kept because a map that starts switched off would
otherwise have dead colliders once it is switched on.
- World.syncToModel looks entities and assets up in a map per pass
instead of a linear search per object.
Measured on stein2 with a copy of the reference project, ms per frame:
Physics 2.64 to 0.97, Drawing 6.89 to 2.56, Editor 1.95 to 1.31.
Left open: syncToModel still mirrors every entity every frame. That
is its own issue.
Tests:
- Gate: 198 files, 2887 tests (2883 + 4), exit 0
- e2e 1-17,28,33,39-43,59: 810 checks passed, 40 has +3
- Smokes: 24 / 19 / 21, exit 0
- Three unit tests wrote cells directly and now call cellsChanged
- Eleven counter-probes fail. Two did not at first: the stroke needed
a check of its own, the physics test has to start with the map
switched off. That last one was repeated on stein2 only.
- e2e total 1613 is computed, not measured in a full run
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 0.02 texel the lines between tiles of a nearest tilemap were gone at
the zooms tried first, but still showed at others. The user raised the
inset to 0.1 by hand and checked it in the browser.
- A tenth of a texel is still far below half a texel, so the texel
picked at every pixel centre stays the same.
- The comment names the new value.
Tests:
- tilemap.test.ts follows the value: the inset test expects 0.1/96,
the sliver test allows up to 0.25 texel from the edge, and the quad
test checks its uvs to 2 digits instead of 3.
- ./check.sh: 156 files, 2314 tests, CHECK EXIT 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At zoom levels that do not land quarter edges on whole screen pixels,
a tilemap whose texture uses Nearest showed one-pixel lines in the
wrong colour. The float uv of a pixel centre right at a quad edge
could round onto the first texel of the neighbouring quarter in the
sheet, which is usually a different tile. Terrain sheets showed it
most, because every tile is four quads there.
- Nearest now pulls the uvs 0.02 texel inside each quarter. That is
far below half a texel, so every picked texel stays the same and
pixel art keeps its size.
- Linear keeps its half-texel inset.
- The first draft used 0.01. The user raised it to 0.02 after
checking the result in the browser.
Tests:
- ./check.sh: 156 files, 2299 tests, CHECK EXIT 0 (before 2298).
- New unit test: every nearest uv sits strictly inside its quarter,
by less than 0.05 texel. Two older tests now expect the inset.
- Counter-check: with no inset for nearest the new test and the
inset test fail.
- No e2e check. The user checked the result in the browser.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>