Project_WL/AgentScripts/WL815c_Survey2.cs

187 lines
9.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// WL-815c 2차 실측 — 링 실제 시각 반경(Simulate 후 바운즈) · 불꽃 파티클 시스템별 상세 · 바위 프롭
// unity command run_script --file AgentScripts/WL815c_Survey2.cs --entry WL815c_Survey2.Run
public static class WL815c_Survey2
{
static System.Text.StringBuilder s_sb;
static void L(string s) { s_sb.AppendLine(s); UnityEngine.Debug.Log(s); }
public static string Run()
{
s_sb = new System.Text.StringBuilder();
L("WL-815c 2차 실측 · " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
L("");
L("── 링 프리팹: Simulate 2 s 후 실제 시각 반경(XZ) ──────────────");
string[] rings = {
"Assets/ResWork/VFX/Hovl Studio/Map track markers VFX/Prefabs/Marker 3 Zone Loop.prefab",
"Assets/ResWork/VFX/Hovl Studio/Map track markers VFX/Prefabs/Marker 5 Circle Loop.prefab",
"Assets/ResWork/VFX/Hovl Studio/Map track markers VFX/Prefabs/Marker 7 Danger zone Loop.prefab",
"Assets/ResWork/VFX/Hovl Studio/Map track markers VFX/Prefabs/Marker 8 Safe zone Loop.prefab",
};
for (int i = 0; i < rings.Length; i++) SimRadius(rings[i]);
L("");
L("── 불꽃 후보: 파티클 시스템별 상세 ────────────────────────────");
string[] fires = {
"Assets/LMHPOLY/Low Poly Nature Bundle/Rocks/Bonus Assets/Prefabs/ParticleSystem/Fire_Particles.prefab",
"Assets/ResWork/VFX/Hovl Studio/Epic Toon VFX 2/Prefabs/Fire buff/Fire buff.prefab",
"Assets/ResWork/EricWang/GameVFX Collection Vol3/Prefabs/FX_Flameflow_floor.prefab",
};
for (int i = 0; i < fires.Length; i++) Detail(fires[i]);
L("");
L("── LMHPOLY 바위(비 LOD · Rock 계열) ───────────────────────────");
var guids = UnityEditor.AssetDatabase.FindAssets("t:Prefab", new string[] { "Assets/LMHPOLY/Low Poly Nature Bundle/Rocks" });
int shown = 0;
for (int i = 0; i < guids.Length && shown < 8; i++)
{
string p = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
string n = System.IO.Path.GetFileNameWithoutExtension(p);
if (p.Contains("/LOD/") || n.EndsWith("_LOD")) continue;
if (!(n.StartsWith("Rock") || n.StartsWith("Stone") || n.StartsWith("Boulder"))) continue;
Brief(p); shown++;
}
if (shown == 0)
{
L(" Rock/Stone/Boulder 접두 프리팹 0 — 폴더 구조 표본:");
for (int i = 0; i < guids.Length && i < 12; i++)
L(" " + UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]));
}
L("");
L("── 울타리 프롭 pivot·회전 확인(둘레 배치 적합성) ───────────────");
string[] fences = {
"Assets/ResWork/LowPolyFantasyVillage_URP/Prefabs/Props/Fence_01.prefab",
"Assets/ResWork/LowPolyFantasyVillage_URP/Prefabs/Props/FenceBig_01.prefab",
"Assets/3DPixelArtEnvironment/Prefabs/Stone_1.prefab",
};
for (int i = 0; i < fences.Length; i++) Pivot(fences[i]);
string outFile = "AgentScripts/WL815c_SURVEY2.txt";
System.IO.File.WriteAllText(outFile, s_sb.ToString());
return "survey2 done → " + outFile;
}
static void SimRadius(string path)
{
var go = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(path);
if (go == null) { L(" [없음] " + path); return; }
var inst = UnityEngine.Object.Instantiate(go);
inst.transform.position = UnityEngine.Vector3.zero;
var pss = inst.GetComponentsInChildren<UnityEngine.ParticleSystem>(true);
for (int i = 0; i < pss.Length; i++) { pss[i].Clear(true); pss[i].Simulate(2.0f, true, true, false); }
float maxR = 0f, maxY = 0f, minY = 0f;
int alive = 0;
for (int i = 0; i < pss.Length; i++)
{
int c = pss[i].particleCount;
alive += c;
if (c == 0) continue;
var buf = new UnityEngine.ParticleSystem.Particle[c];
int got = pss[i].GetParticles(buf);
bool world = pss[i].main.simulationSpace == UnityEngine.ParticleSystemSimulationSpace.World;
for (int k = 0; k < got; k++)
{
var p = buf[k].position;
if (!world) p = pss[i].transform.TransformPoint(p);
float r = new UnityEngine.Vector2(p.x, p.z).magnitude;
float sz = buf[k].GetCurrentSize(pss[i]) * 0.5f;
if (r + sz > maxR) maxR = r + sz;
if (p.y > maxY) maxY = p.y;
if (p.y < minY) minY = p.y;
}
}
// 파티클이 0이면 메시/빌보드 크기로 대신 잰다
float rendR = 0f;
var rends = inst.GetComponentsInChildren<UnityEngine.Renderer>(true);
for (int i = 0; i < rends.Length; i++)
{
var b = rends[i].bounds;
rendR = UnityEngine.Mathf.Max(rendR, UnityEngine.Mathf.Max(b.extents.x, b.extents.z));
}
L(" " + System.IO.Path.GetFileNameWithoutExtension(path));
L(" Simulate(2 s) 살아있는 파티클 " + alive + " · 시각 반경(XZ) " + maxR.ToString("F2") +
" m · 높이 " + minY.ToString("F2") + "~" + maxY.ToString("F2") + " m · 렌더러 바운즈 반경 " + rendR.ToString("F2") + " m");
for (int i = 0; i < pss.Length; i++)
{
var m = pss[i].main;
var sh = pss[i].shape;
var e = pss[i].emission;
string bursts = "";
if (e.burstCount > 0)
{
var arr = new UnityEngine.ParticleSystem.Burst[e.burstCount];
e.GetBursts(arr);
float tot = 0f; for (int k = 0; k < arr.Length; k++) tot += arr[k].count.constantMax * UnityEngine.Mathf.Max(1, arr[k].cycleCount);
bursts = " · 버스트 " + e.burstCount + "종 총 " + tot.ToString("F0");
}
L(" ├ " + pss[i].name + " : max " + m.maxParticles + " · rate " + (e.enabled ? e.rateOverTime.constantMax : 0f).ToString("F1") +
"/s" + bursts + " · life " + m.startLifetime.constantMax.ToString("F2") + " s · size " + m.startSize.constantMax.ToString("F2") +
" · shape " + (sh.enabled ? sh.shapeType.ToString() + " r" + sh.radius.ToString("F2") : "off") +
" · scale " + pss[i].transform.lossyScale.ToString("F2") + " · 지금 " + pss[i].particleCount);
}
UnityEngine.Object.DestroyImmediate(inst);
}
static void Detail(string path)
{
var go = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(path);
if (go == null) { L(" [없음] " + path); return; }
var inst = UnityEngine.Object.Instantiate(go);
var pss = inst.GetComponentsInChildren<UnityEngine.ParticleSystem>(true);
float steady = 0f;
L(" " + System.IO.Path.GetFileNameWithoutExtension(path) + " · PS " + pss.Length);
for (int i = 0; i < pss.Length; i++)
{
var m = pss[i].main; var e = pss[i].emission;
float r = e.enabled ? e.rateOverTime.constantMax : 0f;
float life = m.startLifetime.constantMax;
float st = UnityEngine.Mathf.Min(r * life, m.maxParticles);
steady += st;
L(" ├ " + pss[i].name + " : rate " + r.ToString("F1") + "/s × life " + life.ToString("F2") + " s = " + st.ToString("F0") +
" (max " + m.maxParticles + ") · size " + m.startSize.constantMax.ToString("F2") + " · loop " + (m.loop ? "Y" : "N") +
" · 정지공간 " + m.simulationSpace);
}
L(" ⇒ 인스턴스 1개 정상상태 추정 " + steady.ToString("F0") + " 파티클");
UnityEngine.Object.DestroyImmediate(inst);
}
static void Brief(string path)
{
var go = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(path);
if (go == null) return;
var inst = UnityEngine.Object.Instantiate(go);
var rends = inst.GetComponentsInChildren<UnityEngine.Renderer>(true);
long tris = 0; bool has = false; UnityEngine.Bounds b = default(UnityEngine.Bounds);
for (int i = 0; i < rends.Length; i++)
{
var mf = rends[i].GetComponent<UnityEngine.MeshFilter>();
if (mf != null && mf.sharedMesh != null) tris += mf.sharedMesh.triangles.Length / 3;
if (!has) { b = rends[i].bounds; has = true; } else b.Encapsulate(rends[i].bounds);
}
L(" " + System.IO.Path.GetFileNameWithoutExtension(path) + " · " + path);
L(" 크기 " + b.size.ToString("F2") + " · tri " + tris + " · 렌더러 " + rends.Length);
UnityEngine.Object.DestroyImmediate(inst);
}
static void Pivot(string path)
{
var go = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(path);
if (go == null) return;
var inst = UnityEngine.Object.Instantiate(go);
inst.transform.position = UnityEngine.Vector3.zero;
inst.transform.rotation = UnityEngine.Quaternion.identity;
var rends = inst.GetComponentsInChildren<UnityEngine.Renderer>(true);
bool has = false; UnityEngine.Bounds b = default(UnityEngine.Bounds);
for (int i = 0; i < rends.Length; i++) { if (!has) { b = rends[i].bounds; has = true; } else b.Encapsulate(rends[i].bounds); }
L(" " + System.IO.Path.GetFileNameWithoutExtension(path) + " : pivot→바운즈중심 " + b.center.ToString("F2") +
" · 크기 " + b.size.ToString("F2") + " · 긴축 " + (b.size.x >= b.size.z ? "X " + b.size.x.ToString("F2") : "Z " + b.size.z.ToString("F2")) +
" · 바닥 y " + (b.center.y - b.extents.y).ToString("F2"));
UnityEngine.Object.DestroyImmediate(inst);
}
}