diff --git a/Assets/Scripts/umamusume/Gallop/Live/StageController.cs b/Assets/Scripts/umamusume/Gallop/Live/StageController.cs index 4bdfab0..e5702ee 100644 --- a/Assets/Scripts/umamusume/Gallop/Live/StageController.cs +++ b/Assets/Scripts/umamusume/Gallop/Live/StageController.cs @@ -145,13 +145,23 @@ namespace Gallop.Live private void RestoreAuthoredBlendState() { var done = new HashSet(); + var fixedMats = new Dictionary(); var changed = new List(); + // 材质在舞台上高度共享(live10149:约 1500 个渲染器只有 31 个材质), + // 所以只报材质数会把影响面说小几个数量级 —— 一个 blinklight 材质就铺满整个舞台的灯。 + // 顺带记渲染器数,日志才说得清「改了 1 个材质」到底意味着什么。 + var rendererCount = new Dictionary(); foreach (var r in GetComponentsInChildren(true)) { foreach (var mat in r.sharedMaterials) { - if (mat == null || mat.shader == null || !done.Add(mat)) continue; + if (mat == null || mat.shader == null) continue; + + rendererCount.TryGetValue(mat, out int n); + rendererCount[mat] = n + 1; + + if (!done.Add(mat)) continue; string before = null, after = null; foreach (string prop in kBlendProps) @@ -166,18 +176,27 @@ namespace Gallop.Live } if (after != null) - changed.Add($"{mat.name}[{mat.shader.name}] {before}→ {after}"); + fixedMats.Add(mat, $"{mat.name}[{mat.shader.name}] {before}→ {after}"); } } - if (changed.Count == 0) + if (fixedMats.Count == 0) { Debug.Log($"[StageBlend] {done.Count} 个材质的混合状态与 shader 声明一致,无需修正"); return; } - Debug.Log($"[StageBlend] {changed.Count}/{done.Count} 个材质的 _SrcBlend/_DstBlend 与 shader 声明不符," + - $"已恢复成 shader 的默认值:\n " + string.Join("\n ", changed)); + int affected = 0; + foreach (var kv in fixedMats) + { + rendererCount.TryGetValue(kv.Key, out int n); + affected += n; + changed.Add($"{kv.Value}({n} 个渲染器)"); + } + + Debug.Log($"[StageBlend] {fixedMats.Count}/{done.Count} 个材质的 _SrcBlend/_DstBlend 与 shader 声明不符," + + $"已恢复成 shader 的默认值 —— 共影响 **{affected}** 个渲染器:\n " + + string.Join("\n ", changed)); } private static readonly string[] kBlendProps = { "_SrcBlend", "_DstBlend" }; diff --git a/CLAUDE.md b/CLAUDE.md index 088c0d9..fa2761d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,8 +127,14 @@ pf = obj.read_typetree()["m_ParsedForm"] # m_Name, m_PropInfo.m_Props ⚠️ **实际受害面比存档表窄得多,别照着 26 这个数推。** 只有**当前 shader 真的声明了**这两个 属性的材质才会被读到;其余材质虽然也存着 `One/Zero`,但那只是过期条目,无人问津。 live10149 实测(`[StageBlend]` 日志):31 个材质里**只有 1 个**被修正 —— -`mtl_env_live10149_blinklight000` / `LightBlinkBlend`,`_DstBlend` 0 → 1, -正是地面 wash 灯那批黑楔子。修完实机确认恢复正常。 +`mtl_env_live10149_blinklight000` / `LightBlinkBlend`,`_DstBlend` 0 → 1。 + +**但「1 个材质」严重低估了影响面 —— 材质在舞台上是高度共享的。** 那一个材质铺满 +27 个 BlinkLight 组、约 **1450 个渲染器**(观众席 95、mob000 570、glow_object 67、 +glow_ramp 58、镜面球闪片 83、全部 wash 组、各种 LED 板),实机确认修好的不只是地面 wash 灯的 +黑楔子,长期挂着的「小灯泡渲染成黑块」也一并正常了。 +**教训(第三次同一天):报数要报对单位。** 舞台上约 1500 个渲染器只有 31 个材质, +按材质计数会把影响面说小两个数量级 —— `[StageBlend]` 日志现在同时报渲染器数。 `StageController.RestoreAuthoredBlendState()` 在舞台初始化时把这两个属性写回 **shader 声明的 默认值**(`Shader.GetPropertyDefaultFloatValue`),对本来就该不透明的 shader 是空操作,自限。 改了哪些材质会逐条打进 `[StageBlend]` 日志。 diff --git a/LIVE_TRACKS.md b/LIVE_TRACKS.md index d623315..3fc28bd 100644 --- a/LIVE_TRACKS.md +++ b/LIVE_TRACKS.md @@ -249,7 +249,7 @@ Unity 的 playAutomatically 播的是默认 clip,为空就什么都不播 — | 现象 | 状态 | |---|---| | 舞台地板长期偏亮发白 | ✅ 2026-08-06 解决。**白的不是文档里记的那三个物件** —— 是与 `plane_000` 同位同尺度、叠在一起的 `mirror_a`(同在 `pfb_env_live10149_main000` 下,局部变换全为单位)。它用 `Cygames/MirrorAndShadow/ReceiveMirror`,`_ReflectionRate` 默认 1.0 而 `_ReflectionTex` 从没赋值,Unity 对未绑定采样器代入白贴图 = 满强度白反射。实现 `Gallop.MirrorReflection` 接上反射 RT 后恢复正常。**教训见 `CLAUDE.md`「现象描述不是 ground truth」**:整轮排查都围着文档里那三个名字转,那个「`_EnvRate` 归零无变化」的实验切的是另一批物件 | -| 小灯泡渲染成黑块 / 光柱变实心黑墙 | 🔧 2026-08-07 **找到根因并已修**(待实机确认):Gallop 发光类 shader 的混合状态写作 `Blend [_SrcBlend] [_DstBlend]`,从材质属性读;而 live10149 **26/26 个材质**都被盖上了 URP Lit 的属性表,`_DstBlend` 是 URP Lit 不透明预设的 Zero。全库 16 个声明该属性的 shader 里 **14 个作者默认是 One/One(加法)**,于是**凡是当前 shader 真读这两个属性的**光柱/闪光/投影都被按不透明画 —— 加法下「颜色为黑=不可见」变成了「实心黑墙」。`StageController.RestoreAuthoredBlendState()` 已把这两个属性恢复成 shader 声明的默认值,**实机确认修复**。⚠ 受害面比存档表窄:live10149 实测 31 个材质里只有 1 个真被读到并修正(`mtl_env_live10149_blinklight000` / `LightBlinkBlend`,`_DstBlend` 0→1),其余材质存的是无人问津的过期条目 —— 别拿 26/26 这个数推广。**注**:`StageTransmittedLightMask`/`StageMirrorBallShine` 无颜色属性是另一回事,仍未解 | +| 小灯泡渲染成黑块 / 光柱变实心黑墙 | 🔧 2026-08-07 **找到根因并已修**(待实机确认):Gallop 发光类 shader 的混合状态写作 `Blend [_SrcBlend] [_DstBlend]`,从材质属性读;而 live10149 **26/26 个材质**都被盖上了 URP Lit 的属性表,`_DstBlend` 是 URP Lit 不透明预设的 Zero。全库 16 个声明该属性的 shader 里 **14 个作者默认是 One/One(加法)**,于是**凡是当前 shader 真读这两个属性的**光柱/闪光/投影都被按不透明画 —— 加法下「颜色为黑=不可见」变成了「实心黑墙」。`StageController.RestoreAuthoredBlendState()` 已把这两个属性恢复成 shader 声明的默认值,**实机确认修复**。⚠ 两个方向都别照抄数字:**受害材质**比存档表窄(31 个里只有 1 个真被 shader 读到 —— `mtl_env_live10149_blinklight000` / `LightBlinkBlend`,`_DstBlend` 0→1,其余存的是无人问津的过期条目);但**受害渲染器**远比「1 个材质」多 —— 材质高度共享,那一个铺满 27 个 BlinkLight 组约 1450 个渲染器,所以「小灯泡渲染成黑块」和地面 wash 黑楔子是同一个根因,实机确认一并修好。**注**:`StageTransmittedLightMask`/`StageMirrorBallShine` 无颜色属性是另一回事,仍未解 | | LED 大屏黑屏 | MonitorControl (10) 未实现,见上 | ---