187 lines
9.9 KiB
C#
187 lines
9.9 KiB
C#
|
|
// 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);
|
|||
|
|
}
|
|||
|
|
}
|