97 lines
5.3 KiB
C#
97 lines
5.3 KiB
C#
// ─────────────────────────────────────────────────────────────────────────────
|
||
// WLDungeonGrassInstancer.cs — 던전 데모 인스턴서의 「물 밑 풀 빼기」판 (#851 · 2026-10-12)
|
||
//
|
||
// PD 「던전에 들어갈 경우 일부 잔디 이미지가 어색하게 보이는 현상(원형 지역에 패턴처럼 듬성듬성 나있는 지형)을 자연스럽게」.
|
||
// 실측(WL_Dungeon01): 지형 스플랫이 전부 풀 층이라 데모 인스턴서가 **둥근 연못 바닥에도** 풀잎을 심었고,
|
||
// 풀잎이 투명한 물 너머로 격자처럼 비쳤다(연못 바닥 −0.85 m · 수면 −0.10 m).
|
||
//
|
||
// ■ 하는 일 — 원본 `TerrainInstancesBehaviour` 의 생성 결과를 그대로 받아, 수면 사각형 안이면서 지형 높이가
|
||
// 수면보다 `margin` 이상 낮은 점(= 물에 잠긴 뿌리)만 뺀다. 원본 스크립트 0줄 · 씬 파일 0줄.
|
||
// ■ 교체 방법 — `Replace` 가 정보를 정적 칸에 둔 뒤 AddComponent 한다 → Awake 에서 원본 값을 복사하고 OnEnable 에서 한 번에 심는다
|
||
// (AddComponent 직후 빈 값으로 OnEnable 이 돌면 데모 스크립트가 LogError → 오류 팝업 · 813z 규칙).
|
||
// 🔴 Debug.LogError / Debug.LogException 을 쓰지 않는다.
|
||
// ─────────────────────────────────────────────────────────────────────────────
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using DemoInstancer = global::Environment.Instancing.TerrainInstancesBehaviour;
|
||
using DemoSettings = global::Environment.Instancing.InstancingSettings;
|
||
using DemoData = global::Environment.Instancing.InstanceData;
|
||
|
||
namespace WL.Look.Farm
|
||
{
|
||
public sealed class WLDungeonGrassInstancer : DemoInstancer
|
||
{
|
||
/// <summary>수면 하나 — 렌더러 바운즈의 xz 사각형 + 수면 높이.</summary>
|
||
public struct Pool { public float minX, maxX, minZ, maxZ, surfaceY; }
|
||
|
||
// ── 진단(프로브·로그가 읽는다)
|
||
public static int LastKept, LastDropped;
|
||
|
||
readonly List<Pool> _pools = new List<Pool>();
|
||
float _margin;
|
||
|
||
struct Setup { public DemoInstancer src; public List<Pool> pools; public float margin; }
|
||
static Setup? s_next;
|
||
|
||
/// <summary>원본을 끄고(버퍼 해제는 호출 쪽) 같은 오브젝트에 이 판을 붙여 다시 심는다. 돌려주는 값 = 새 인스턴서(실패 시 null).</summary>
|
||
public static WLDungeonGrassInstancer Replace(DemoInstancer src, List<Pool> pools, float margin)
|
||
{
|
||
if (src == null || src.GetComponent<Terrain>() == null) return null;
|
||
var have = src.GetComponent<WLDungeonGrassInstancer>();
|
||
if (have != null) return have;
|
||
s_next = new Setup { src = src, pools = pools, margin = margin };
|
||
try { return src.gameObject.AddComponent<WLDungeonGrassInstancer>(); } // Awake(값 복사) → OnEnable(심기)
|
||
finally { s_next = null; }
|
||
}
|
||
|
||
void Awake()
|
||
{
|
||
if (!s_next.HasValue) return;
|
||
var s = s_next.Value;
|
||
FirstLayer = s.src.FirstLayer; SecondLayer = s.src.SecondLayer; ThirdLayer = s.src.ThirdLayer; FourthLayer = s.src.FourthLayer;
|
||
PositionVariance = s.src.PositionVariance; ScaleVariance = s.src.ScaleVariance;
|
||
_pools.Clear(); if (s.pools != null) _pools.AddRange(s.pools);
|
||
_margin = Mathf.Max(0f, s.margin);
|
||
}
|
||
|
||
public override Dictionary<DemoSettings, List<DemoData>> GetInstanceData()
|
||
{
|
||
var data = base.GetInstanceData();
|
||
if (data == null || _pools.Count == 0) return data;
|
||
var t = GetComponent<Terrain>();
|
||
if (t == null || t.terrainData == null) return data;
|
||
|
||
// 원본은 위치에서 지형 바운즈 중심을 빼고, 그릴 때 「바운즈 중심 + 터레인 위치」를 더한다 → 월드 = 이 원점 + TRS 위치
|
||
Vector3 origin = t.transform.position + t.terrainData.bounds.center;
|
||
int kept = 0, dropped = 0;
|
||
var result = new Dictionary<DemoSettings, List<DemoData>>(data.Count);
|
||
foreach (var kv in data)
|
||
{
|
||
var list = kv.Value;
|
||
var keep = new List<DemoData>(list.Count);
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
Vector4 c = list[i].TRS.GetColumn(3);
|
||
if (Underwater(t, new Vector3(origin.x + c.x, 0f, origin.z + c.z))) { dropped++; continue; }
|
||
keep.Add(list[i]); kept++;
|
||
}
|
||
result.Add(kv.Key, keep);
|
||
}
|
||
LastKept = kept; LastDropped = dropped;
|
||
return result;
|
||
}
|
||
|
||
bool Underwater(Terrain t, Vector3 w)
|
||
{
|
||
for (int i = 0; i < _pools.Count; i++)
|
||
{
|
||
var p = _pools[i];
|
||
if (w.x < p.minX || w.x > p.maxX || w.z < p.minZ || w.z > p.maxZ) continue;
|
||
float h = t.SampleHeight(w) + t.transform.position.y;
|
||
if (h < p.surfaceY - _margin) return true;
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
}
|