[WL-816w] 울타리 진범 = FI 타일 메시에 구워진 난간 — 타일 메시 복제 후 윗면 위 삼각형 제거(WLIslandTileFenceStrip · stripBakedFences 1) · 섬 윤곽 풀 라운드 R 3 m·넘침 0.6 (PD 실측 지시 · #816)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
깃 관리자 2026-09-15 18:17:03 +09:00
parent b55c69821b
commit 70a3eb380f
4 changed files with 87 additions and 2 deletions

View File

@ -90,6 +90,7 @@ namespace WL.Island
bool haveFarm = HideFarms(cfg, scene, out farmCenter);
HideIslandFences(cfg, scene, null);
WLIslandTileFenceStrip.Apply(cfg, scene); // 2026-09-15 Lead 실측 — 타일 메시에 구워진 난간 제거
// 2026-09-15 PD 「게임 시작 시 섬에 울타리가 여전히 남아 있다」 — 시작 직후 FI 타일 활성화가 렌더러를 다시 켜므로
// farmReHideDelaySeconds 간격으로 3회 더 훑는다(이미 꺼진 것은 건너뛴다 · 값 0 이면 무동작).
if (cfg.hideIslandFences != 0 && WLIslandBridge.Runner != null)
@ -459,6 +460,7 @@ namespace WL.Island
yield return new WaitForSeconds(wait);
if (cfg == null || cfg.hideIslandFences == 0 || !scene.IsValid() || !scene.isLoaded) yield break;
HideIslandFences(cfg, scene, null);
WLIslandTileFenceStrip.Apply(cfg, scene); // 확장·재구성으로 타일 메시가 바뀌면 다시 잘라낸다(멱등)
if (cfg.hideFarms != 0) { Vector3 _c; HideFarms(cfg, scene, out _c); } // 늦게 생긴 밭의 울타리·소품도
}
}

View File

@ -292,6 +292,12 @@ namespace WL.Island
[Tooltip("2026-09-15 PD 「흙 지역도 라운딩」 — 밭 사각형 모서리에서 이 거리(m · 맨해튼 dx+dz) 안의 흙칸은 숨긴다. 0 = 무동작(사각형 그대로).")]
public float soilCornerRadius = 1.6f;
[Tooltip("🔴 2026-09-15 Lead 실측 — 남은 울타리는 별도 오브젝트가 아니라 **FI 타일 메시에 구워진 난간**이다. 1 이면 타일 메시를 복제해 윗면 위로 솟은 삼각형을 잘라낸다(원본 메시 무수정 · WLIslandTileFenceStrip). 0 = 원본 메시 그대로.")]
public int stripBakedFences = 1;
[Tooltip("이 높이(m · 타일 로컬 y · 윗면 = 0)보다 위에 정점이 하나라도 있는 삼각형을 난간으로 보고 버린다.")]
public float fenceStripMinY = 0.15f;
[Tooltip("🔴 §1 — 1 이면 **새로 열린 타일**의 머티리얼 배열을 이미 열려 있는 타일과 **같게** 만든다. " +
"실측: 바닥 색 자체는 이미 같지만(main b1e58d795), 새 타일만 외곽선 패스(WL/HullOutline)를 " +
"못 받아 경계에서 테두리 유무가 갈린다. 새 머티리얼을 만들지 않고 기존 배열을 물려준다.")]

View File

@ -0,0 +1,77 @@
// ─────────────────────────────────────────────────────────────────────────────
// WLIslandTileFenceStrip.cs — FI 섬 타일 메시에 **구워진 난간(울타리)** 을 잘라낸다.
//
// 2026-09-15 Lead 가 실행 중인 화면을 직접 실측:
// · 별도 오브젝트 `Island (n)/Fence01*` 은 렌더러·콜라이더가 이미 꺼져 있고 SetActive(false) 해도 화면의 울타리는 그대로.
// · 풀 인스턴싱을 꺼도 그대로. 화면 안 렌더러 전수 = 타일(04·07·26·34)·물·캠프·플레이어뿐.
// → 남은 울타리는 **타일 메시 자체에 포함된 삼각형**(재질 1개 · 서브메시 1개 · 브라운 = 텍스처 흙 사분면)이다.
// 조치 = 타일 메시를 복제해 윗면(y=0) 위로 `fenceStripMinY` 이상 솟은 삼각형만 버리고 그 복제본을 물린다.
// 원본 메시·FI 코드 0줄 · 되돌리기 `stripBakedFences 0`(다음 로드부터 원본 메시).
// 🔴 모바일 빌드에서는 FI 타일 FBX 의 Read/Write 가 꺼져 있으면 정점을 못 읽는다(에디터는 읽힌다) — 그때는 임포트 설정 1개 변경 필요.
// ─────────────────────────────────────────────────────────────────────────────
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using FIIsland = CryingSnow.FarmingIsland.Island;
namespace WL.Island
{
public static class WLIslandTileFenceStrip
{
static readonly Dictionary<Mesh, Mesh> s_cache = new Dictionary<Mesh, Mesh>();
public static int TilesStripped, TrianglesRemoved, Unreadable;
public static string LastLog = "";
/// <summary>섬 씬의 타일(FI Island)마다 메시를 검사해 난간 삼각형이 있으면 잘라낸 복제본으로 바꾼다(멱등).</summary>
public static void Apply(WLIslandSettings cfg, Scene scene)
{
if (cfg == null || cfg.stripBakedFences == 0) return;
var isls = Object.FindObjectsByType<FIIsland>(FindObjectsInactive.Include, FindObjectsSortMode.None);
int changed = 0;
for (int i = 0; i < isls.Length; i++)
{
var isl = isls[i];
if (isl == null || (scene.IsValid() && isl.gameObject.scene != scene)) continue;
var mf = isl.GetComponent<MeshFilter>();
if (mf == null || mf.sharedMesh == null) continue;
var src = mf.sharedMesh;
if (src.name.EndsWith("_nofence")) continue;
Mesh dst;
if (!s_cache.TryGetValue(src, out dst)) { dst = Strip(src, cfg.fenceStripMinY); s_cache[src] = dst; }
if (dst != null && dst != src) { mf.sharedMesh = dst; TilesStripped++; changed++; }
}
if (changed > 0)
{
LastLog = "타일 난간 제거 — 타일 " + changed + "개 · 누적 삼각형 " + TrianglesRemoved;
WLIslandBridge.Log(cfg, LastLog);
}
}
static Mesh Strip(Mesh src, float minY)
{
Vector3[] verts; int[] tris;
try { verts = src.vertices; tris = src.triangles; }
catch (System.Exception) { Unreadable++; return src; } // Read/Write 꺼진 메시 — 손대지 않는다
if (verts == null || tris == null || tris.Length < 3) return src;
var keep = new List<int>(tris.Length);
int removed = 0;
for (int t = 0; t + 2 < tris.Length; t += 3)
{
int a = tris[t], b = tris[t + 1], c = tris[t + 2];
if (verts[a].y > minY || verts[b].y > minY || verts[c].y > minY) { removed++; continue; }
keep.Add(a); keep.Add(b); keep.Add(c);
}
if (removed == 0) return src;
var m = Object.Instantiate(src);
m.name = src.name + "_nofence";
m.triangles = keep.ToArray();
m.RecalculateBounds();
TrianglesRemoved += removed;
return m;
}
}
}

View File

@ -114,8 +114,8 @@ MonoBehaviour:
farmEdgeNoise: 0.4
farmEdgeNoiseCell: 0.5
outlineRoundEnabled: 1
outlineRoundRadius: 1.5
outlineOverhang: 0.3
outlineRoundRadius: 3
outlineOverhang: 0.6
outlineRoundCell: 0.25
propMargin: 0.05
propMaxSize: 7.5