From 0ce4133dc8bbd01ce1ffd1ab583f41f1efee869f Mon Sep 17 00:00:00 2001 From: swrring Date: Wed, 16 Sep 2026 19:59:01 +0900 Subject: [PATCH] =?UTF-8?q?[WL-816w/816zj]=20=EC=9A=B8=ED=83=80=EB=A6=AC?= =?UTF-8?q?=20=EA=B3=A0=EC=95=84=20=EC=86=8C=ED=83=95(StageBarrierVisual.S?= =?UTF-8?q?weepOrphans=20=E2=80=94=20HideAndDontSave=20=EB=A3=A8=ED=8A=B8?= =?UTF-8?q?=EA=B0=80=20Play=20=EC=A2=85=EB=A3=8C=20=ED=9B=84=20=EC=82=B4?= =?UTF-8?q?=EC=95=84=EB=82=A8=EB=8D=98=20=EA=B2=83=20=C2=B7=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=20=EC=8B=9C=2014=EA=B0=9C=20=EC=A0=9C=EA=B1=B0)=20?= =?UTF-8?q?=C2=B7=20=EB=8D=B0=EB=AA=A8=20=EC=9E=AC=EC=A7=88=20=EA=B5=AC?= =?UTF-8?q?=EB=A6=84=20=EA=B0=95=EB=8F=84=20=EB=9F=B0=ED=83=80=EC=9E=84=20?= =?UTF-8?q?=EB=B3=B5=EC=82=AC=EB=B3=B8=20demoCloudStrength=200.3(=EC=9B=90?= =?UTF-8?q?=EB=B3=B8=20=EB=AC=B4=EC=88=98=EC=A0=95=20=C2=B7=20=E3=80=8C?= =?UTF-8?q?=EC=96=BC=EB=A3=A9=EB=8D=9C=EB=A3=A9=E3=80=8D=20A/B=20=EC=8B=A4?= =?UTF-8?q?=EC=B8=A1)=20(#816)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- .../Stage/Barrier/StageBarrierVisual.cs | 27 ++++++++++++++++++- Assets/WL/Look/Farm/WLDemoTerrain.cs | 24 +++++++++++++++-- Assets/WL/Look/Farm/WLIslandLookSettings.cs | 4 +++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Assets/WL/Combat/Stage/Barrier/StageBarrierVisual.cs b/Assets/WL/Combat/Stage/Barrier/StageBarrierVisual.cs index 3b501d3ca..88fc59adc 100644 --- a/Assets/WL/Combat/Stage/Barrier/StageBarrierVisual.cs +++ b/Assets/WL/Combat/Stage/Barrier/StageBarrierVisual.cs @@ -153,7 +153,7 @@ namespace WL.Combat.Stage /// public static int HideImmediate() { - int n = s_live.Count; + int n = s_live.Count + SweepOrphans(); s_showing = false; if (n == 0 && s_t <= 0f) return 0; ApplyPhase(0f); @@ -162,6 +162,31 @@ namespace WL.Combat.Stage return n; } + /// + /// 2026-09-16 Lead 실측 — 섬에서 보인 울타리·바위 13개는 이번 세션의 장벽이 아니었다(`HasActive=false · Shows=0`). + /// 루트가 HideAndDontSave 라 **에디터 Play 종료·도메인 리로드 뒤에도 살아남고**, 정적 참조(s_root)만 끊겨 고아가 된 것. + /// 이름이 같은 루트 중 현재 s_root 가 아닌 것을 전부 지운다(Play 시작 시·섬 진입 시·즉시 숨김 때). + /// + public static int SweepOrphans() + { + int n = 0; + var all = Resources.FindObjectsOfTypeAll(); + for (int i = 0; i < all.Length; i++) + { + var t = all[i]; + if (t == null || t.parent != null || t.name != "[WL815c] StageBarrierVisual") continue; + if (s_root != null && t == s_root) continue; + if (Application.isPlaying) Object.Destroy(t.gameObject); else Object.DestroyImmediate(t.gameObject); + n++; + } + OrphansSwept += n; + return n; + } + public static int OrphansSwept; + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + static void SweepOnBoot() { s_root = null; SweepOrphans(); } + /// 연출 진행. StageBarrier.Tick 이 부른다. internal static void Tick(WLStageBarrierSettings cfg) { diff --git a/Assets/WL/Look/Farm/WLDemoTerrain.cs b/Assets/WL/Look/Farm/WLDemoTerrain.cs index db2897cd1..d9d486990 100644 --- a/Assets/WL/Look/Farm/WLDemoTerrain.cs +++ b/Assets/WL/Look/Farm/WLDemoTerrain.cs @@ -478,7 +478,8 @@ namespace WL.Look.Farm // 🔴 2026-09-16 PD 「상인 생성 때 맵이 잠시 사라진 것처럼 보임」 — 같은 값을 다시 대입해도 Terrain 이 내부 상태를 다시 만들어 한 프레임 비는 것을 막는다(바뀔 때만 대입). if (_terrain.terrainData != _data) _terrain.terrainData = _data; - if (_terrain.materialTemplate != cfg.demoTerrainMaterial) _terrain.materialTemplate = cfg.demoTerrainMaterial; // 데모 Terrain.mat 그대로(값 무수정) + var tmat = Tuned(cfg.demoTerrainMaterial); // 데모 Terrain.mat 그대로(값 무수정) · 구름 강도만 섬 크기에 맞춘 런타임 복사본 + if (_terrain.materialTemplate != tmat) _terrain.materialTemplate = tmat; if (_terrain.drawInstanced) _terrain.drawInstanced = false; // Demo.unity 1228 m_DrawInstanced 0 · 그 외 Terrain 값은 데모 = 컴포넌트 기본값 if (_terrain.allowAutoConnect) _terrain.allowAutoConnect = false; } @@ -537,7 +538,26 @@ namespace WL.Look.Farm if (mesh == null) { why = label + " 메시 없음(scatter[" + d.scatterIndex + "])"; return null; } if (demoMat == null) { why = label + " 데모 재질 비어 있음"; return null; } if (d.scale <= 0f) { why = label + " scale ≤ 0"; return null; } - return new DemoEntry { Mesh = mesh, Material = demoMat, Probability = d.probability, Scale = d.scale, NormalOffset = d.normalOffset }; + return new DemoEntry { Mesh = mesh, Material = Tuned(demoMat), Probability = d.probability, Scale = d.scale, NormalOffset = d.normalOffset }; + } + + // ───────────────────────────────────────────────────────────────── + // 2026-09-16 PD 「풀이 얼룩덜룩」 실측(A/B): 데모 원값 `_Cloud_Strength 1.0` 은 200 m 지형에 맞춘 값이라 32 m 섬은 절반이 통째로 50 % 어둡게 덮여 + // 얼룩처럼 보였다. 원본 재질은 손대지 않고 **런타임 복사본**에 `demoCloudStrength` 만 덮어쓴다(0 이하 = 원본 그대로). + // ───────────────────────────────────────────────────────────────── + readonly Dictionary _tuned = new Dictionary(); + Material Tuned(Material src) + { + if (src == null) return null; + if (cfg == null || cfg.demoCloudStrength <= 0f || !src.HasProperty("_Cloud_Strength")) return src; + Material m; + if (!_tuned.TryGetValue(src, out m) || m == null) + { + m = new Material(src) { name = src.name + "(WL cloud " + cfg.demoCloudStrength.ToString("F2") + ")", hideFlags = HideFlags.DontSave }; + _tuned[src] = m; + } + if (!Mathf.Approximately(m.GetFloat("_Cloud_Strength"), cfg.demoCloudStrength)) m.SetFloat("_Cloud_Strength", cfg.demoCloudStrength); + return m; } } } diff --git a/Assets/WL/Look/Farm/WLIslandLookSettings.cs b/Assets/WL/Look/Farm/WLIslandLookSettings.cs index 2f0274e0d..3aee9e568 100644 --- a/Assets/WL/Look/Farm/WLIslandLookSettings.cs +++ b/Assets/WL/Look/Farm/WLIslandLookSettings.cs @@ -400,6 +400,10 @@ namespace WL.Look.Farm "타일 윗면 렌더러는 숨긴다(콜라이더 유지 = 걷기·밭·수확 그대로). 0 = 지금 구조 100 % 복귀.")] public int demoTerrainEnabled = 1; + [Tooltip("데모 지형·풀·꽃 재질의 구름 그림자 강도를 이 값으로 덮어쓴 런타임 복사본을 쓴다(원본 무수정). " + + "2026-09-16 PD 「풀이 얼룩덜룩」 A/B 실측: 데모 원값 1.0 은 200 m 지형용이라 32 m 섬이 통째로 어두워졌다 → 0.3. 0 이하 = 원본 그대로.")] + public float demoCloudStrength = 0.3f; + [Tooltip("높이맵 해상도(2ⁿ+1 · 33~4097). 129 = 한 변 128 m 일 때 1 m 간격, 작은 섬이면 더 촘촘해진다.")] public int terrainHeightRes = 129;