The log said "1 of 31 materials corrected" and that read like a one-off fix for one lamp, which
prompted the reasonable question of why far more than one lamp got better. The count was right
and the unit was wrong.
Materials are heavily shared here: roughly 1500 renderers across live10149 draw from 31 unique
materials. The single corrected one, mtl_env_live10149_blinklight000 on LightBlinkBlend, is the
blink-light material for the entire stage — it appears in all 27 BlinkLight groups, about 1450
renderers: audience_light 95, mob000 570, glow_object 67, glow_ramp 58, the mirror ball flare
quads 83, every wash group, and the LED panels. So the same fix that cleared the ground wash
wedges is also why the small bulbs stopped rendering as black blocks, which had been sitting in
LIVE_TRACKS.md as an unexplained symptom.
The log now counts affected renderers alongside materials and prints the per-material tally, so
the blast radius is legible without cross-referencing the BlinkLight lines by hand.
Both docs are corrected in the same pass. The earlier note narrowed the claim correctly — only
materials whose current shader declares the property are touched — but by leading with "only 1"
it understated the result in the other direction. That is three scope misstatements about this
one fix in a day, so the rule now sits next to it: report the unit that matches the question
being asked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
The fix is confirmed working — the black wedges are gone — but the log corrects the scope I
wrote yesterday. [StageBlend] reports 1 of 31 materials corrected, not the 26 the offline dump
suggested: mtl_env_live10149_blinklight000 on LightBlinkBlend, _DstBlend 0 -> 1, which is
exactly the ground wash beams.
Both numbers are right about different things. All 26 materials do store One/Zero, but a stored
value only matters when the current shader declares the property and reads it as render state.
Everywhere else it is another stale saved-properties entry that nothing consults — the same
trap this file already warns about, which I then walked into while describing the fix. The
self-limiting design held: only shader-declared properties were touched, so the other 30
materials were left alone.
Corrected in both places rather than left standing, since an overstated claim in these files is
what cost the most time this week.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
Its premise was that a single clip is an unambiguous instruction to play. It is not — it means
the object has one state, while whether that state is running was AnimationObjectController's
per-frame decision, and that class has zero serialized fields, so no amount of dumping recovers
it. What was left was policy invented here: the wash lights whipping through a 2-second sweep
the original does not perform, and a mirror ball turning at a rate nothing can validate.
After today's exclusions it took over exactly one object on live10149. Two hundred lines to spin
one ball at a speed we cannot check, in a subsystem that also claims — by existing — that this
area has been dealt with. That last part is the real cost: a wrong stand-in reads as done and
stops anyone looking again.
So the stage's 283 Animation components now play nothing, deliberately. The disco balls do not
turn, the wash lights do not sweep, the neon signs do not move. That is the honest state given
what is recoverable, and it is the prefab author's pose rather than our invention.
The file is renamed to StageMissingScriptCensus.cs, keeping only the census that was sharing it
— that one is a genuine progress meter for rebuilt signatures and never had anything to do with
animation playback.
One finding survives the deletion and is written into LIVE_TRACKS.md so a future attempt starts
from it rather than rediscovering it: do not drive stage animation with Animation.Play(), which
runs on Unity's own clock and desyncs the moment the live is paused or the scrubber moves. Set
AnimationState.time from LiveTimelineControl.currentLiveTime (seconds) and Sample(). The same
entry records why the feature is off, what would be needed to revive it (per-stage calibration
against reference footage, or IL2CPP metadata), and that the clip assets themselves are fully
readable — which is the trap, since knowing the asset says nothing about when the original plays
it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
Two of this session's bugs had the same shape, and naming that shape is worth more than either
fix: the wash lights whipping back and forth, and the billboards spinning. In both cases the
data was fine — clip curves and serialized fields dumped clean and checked out — and what was
wrong was behaviour we had inferred on behalf of a script that does not exist.
So the default hypothesis for "this stage element moves when it shouldn't / doesn't move when it
should / moves at the wrong rate" is now written down as: the original component is missing and
something of ours is standing in for it. Not: the data was parsed wrong. That is justified by
the ledger — 728 MonoBehaviour instances are still empty, AnimationObjectController alone
accounting for 282, and every decision about what animates and when lived in those method
bodies. Data is dumpable and has repeatedly proven correct; behaviour is the part we cannot
retrieve.
Two practical corollaries go with it: check what scripts an object carried and whether we have
them ([StageScripts] plus the signature list) before suspecting the parser; and when standing in
for a missing component, say in the source whose decisions you are making, and mark whether the
rule came from bundle data or from watching reference footage. The latter is real evidence but
not ground truth, and may not hold on another stage.
The counter-example is recorded in the same breath so the rule does not become a reflex: the
black light shafts were a data problem after all — every material carries a URP Lit property
table whose opaque preset (_DstBlend = Zero) overrode the additive blend 14 of the 16 relevant
shaders declare. That one was found by dumping, and the general lesson — a stale saved-property
table can override render state, not just colour — now sits next to the existing warning about
saved properties.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
Chased the lead that MirrorBallProjector's shader might cross-validate the ball's rotation
speed. It does — by showing there was never an unknown constant to recover.
* All four MirrorBallProjector instances on live10149 carry MirrorBallIsLoopRotation = 0,
MirrorBallLoopRotationSpeed = 0, MirrorBallLoopRotationValue = 0. The shader's own
loop-rotation path is switched off on this stage, so it is not the rotation source.
* The source is the clip StageAnimationPlayer already plays. Its six quaternion curves
(mirrorball_a_000 and b_000..004) give a constant -179.50 deg/s about Y — the same figure
at every one of the seven keys — 2.0 s per loop, last key -359 deg so the loop seam does
not repeat a frame. The ball speed in our build is therefore already correct.
The general lesson is recorded too: "the value is 0" and "the value is unknown" are different
findings, and this one was filed as the latter for weeks. Check the enable flag before
declaring a constant unrecoverable.
What genuinely is blocked here is narrower than "the script's behaviour": the shader wants
_MirrorBallPosWS / _MirrorBallScale / _MirrorBallRotateValue, the component holds no reference
to any ball, all four projectors sit at the origin sharing one material, and the balls are at
six scattered positions. The object-to-object binding lives in the method body. The Blocked
section now says that instead of using this field as its example.
Two other things fell out of the same dump pass:
* LensFlare is not a "build a system from scratch" item at all. CustomLensFlare's Flare
points at Gallop.RenderPipeline.LensFlareData — a ScriptableObject in the same assembly,
so rebuildable by signature — whose fields are a verbatim copy of Unity's legacy Flare
(TextureLayout, Texture, ElementArray[ImageIndex/Position/Size/Color/UseLightColor/
Rotate/Zoom/Fade], UseFog). That means the semantics are Unity's own and not blocked by
IL2CPP, and URP ships LensFlareComponentSRP as the target. 199+5 objects carry it, and
the stage has no legacy LensFlare component anywhere. Promoted to the next thing to do.
* ShaderParamController, previously ranked "cheapest", is a no-op: its only two entries are
_AmbientColor and _CharaColor, both (1,1,1,1). Struck from the list rather than left as
bait.
The stale-saved-properties warning gains a worked example, because mtl_env_live10149_
projector001 is a good one: 40+ saved entries against 22 real ones, including _IsLoopYRotation
and _LoopYRotationSpeed, which are older spellings of properties that do exist — a near-miss
that reads as a discovery.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
Several rows had gone stale, and two of them were actively misleading — the kind that sends
the next session down a path that has already been closed.
Corrected claims:
* "LensFlare — UmaBuild has no source" is wrong. Rebuilding a class from its signature gets
the real serialized fields; only the method bodies are unrecoverable. The row is marked as
a correction rather than quietly edited, because it is the assumption that kept 892
MonoBehaviour slots written off as unreachable.
* "Environment (58) — planar reflection does not exist at all" is no longer true.
MirrorReflection implements the whole second-camera -> RT -> mirror-shader path; what the
track still needs is its keyframes routed into it, which is a much smaller job than the
"build a rendering system from scratch" tier it was filed under.
* The floor blow-out and the BlinkLight palette slot mapping are both listed as open
problems in LIVE_TRACKS.md. Both are solved; the slot rule is recorded (slot = the
lightNNN_/alphaNNN_ prefix of the renderer or its nearest ancestor), and the floor entry
keeps the fact that the symptom belonged to a different object than the one documented,
since that is the reusable part.
* The audit's C4 row still said "located to DefaultEnvMapNoAmbient, diagnostic added", which
the section below it had already overturned.
Added: the stage-script table now carries per-class status, so the two that are built are
distinguishable from the eight that are not; what a rebuilt signature does and does not give
you (MirrorReflection got behaviour because the receiving shader was identifiable,
BillboardController stopped at data because _rotationType is an enum); StageAnimationPlayer
and why it samples currentLiveTime instead of calling Animation.Play(); the shared property
block convention and the Get -> modify -> Set rule that goes with it; HdrBloom marked as
deliberately handler-less rather than "safe to delete".
The audit gains a closing section for the work that came after it, and its suggested order now
records which items landed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UzXXkLzVC8pNA3JjyUGMbq
The pre-2026-08-04 scan data was wrong in two systematic ways, and acting on
it wasted real time. Re-measured everything with tools/ against all 59 songs.
* Eleven tracks marked "WorkSheet 无 X 字段" do have the field, several with
substantial data: MobControlKeys (2392 keys), CyalumeControlKeys (2372),
nodeScaleList (57/59 songs), monitorCameraPos/LookAtKeys, sweatLocatorList,
facialNoiseKeys, charaMotionNoiseKeys, LipSyncPattern*, and the multi-camera
bloom keys. These are "just needs a C# declaration", not blocked.
* Six tracks marked "全 0 keyframe 空占位" carry thousands of keys. PostFilm
is the worst case at ~20200 keys over 59/59 songs; live-shader-todo.md was
right to rank it first and LIVE_TRACKS.md was wrong to write it off.
Rows that have been re-measured are tagged ✅实测; untagged rows are still old
data and should be re-verified before anyone acts on them. Priorities are now
ordered by measured data volume crossed with the kind of work required.
Also recorded:
* The stage shader colour/brightness channel table, and the warning that a
material's m_SavedProperties lists properties its current shader no longer
has — enumerate the shader, never trust that table.
* A working rule: no ground truth, no implementation. Guessing cost two wrong
PostFilm vignette implementations before it turned out the defining shader
is not shipped in any bundle. Note that "the property exists" is not "this
field maps to that property" — that distinction is why BgColor1's power ->
_ColorPower write was reverted while BlinkLight's was kept.
* A 「已知未解问题」 section splitting open items into: has ground truth so
can be built, lacks it so disabled, and rendering problems unrelated to the
timeline (the stage floor blowing out predates all of this work; the small
bulbs render black because their shaders expose no colour property at all).
* Song 1177 (stage live10149) is the reference song used throughout. Earlier
notes said 1157, which was wrong — that song uses stage live10146.
* The old UmaCrack tool paths are gone; tools/ replaces them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replace broad Contains("light") with IsTimelineControlledLight() that matches
only objects actually controlled by timeline handlers (blinklight, spotlight3d,
_wash_, laser). Neonsigns, glow meshes, UV scroll objects and other static stage
props now keep their prefab default state instead of being silently disabled.
Also fix UVScrollLight handler to use GetComponentsInChildren<Renderer>(true)
so inactive renderers are included in material search.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
scrollSpeedX/Y was incorrectly passed to SetTextureScale (tiling),
now accumulated as per-frame offset delta on top of keyframe scrollOffsetX/Y.
Added _uvScrollAccum dict cleared on InitializeTimeline.
Also updated LIVE_TRACKS.md with full-scan coverage numbers and
live-shader-todo.md with blocked-track categorization.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix LiveTimelineBgColor2Data.keys type (BgColor1DataList → BgColor2DataList)
- Add AlterUpdate_BgColor2 call and implementation in LiveTimelineControl
- Subscribe OnUpdateBgColor2 in Director with ambient color handler
- Extract all anonymous delegates in Director to named OnXxxUpdate methods
- Add LIVE_TRACKS.md: full track reference table (IDs 0–102)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>