[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:
parent
b55c69821b
commit
70a3eb380f
|
|
@ -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); } // 늦게 생긴 밭의 울타리·소품도
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)를 " +
|
||||
"못 받아 경계에서 테두리 유무가 갈린다. 새 머티리얼을 만들지 않고 기존 배열을 물려준다.")]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue