Project_WL/AgentScripts/WL814k_Survey.cs

206 lines
10 KiB
C#
Raw Permalink Normal View History

// WL-814k 실측 조사 (게임 코드 아님 · 에디트 모드 전용 · 에셋 수정 0 · 읽기만)
// run: unity command run_script --file AgentScripts/WL814k_Survey.cs --entry WL814k_Survey.Run
// 🔴 원본 프리팹/머티리얼/애니메이션 수정 0. AssetDatabase.SaveAssets 호출 0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
public static class WL814k_Survey
{
const string kTxt = "AgentScripts/WL814k_SURVEY.txt";
static StringBuilder s_sb;
static void L(string s) { s_sb.AppendLine(s); Debug.Log("[WL814k] " + s); }
public static void Run()
{
s_sb = new StringBuilder();
L("WL-814k 실측 조사 · " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " · Unity " + Application.unityVersion);
try
{
Cam();
Prefab("Assets/Res_Addr/PC/Ai01.prefab");
Prefab("Assets/Res_Addr/Mobs/Mob/Batty_A.prefab");
Counts();
ToonMats();
}
catch (Exception ex) { L("EXCEPTION " + ex); }
File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false));
Debug.Log("[WL814k] → " + kTxt);
}
// ── ① 카메라 각 (811o 수식 그대로 · 814d 프리셋 값) ──────────────────────
static void Cam()
{
L("");
L("== ① 카메라 각 (WLLookModeSettings 프리셋 실측) ==");
var so = Resources.Load<WL.Look.Toggle.WLLookModeSettings>("WL/WLLookModeSettings");
if (so == null) { L(" WLLookModeSettings 없음"); return; }
for (int i = 0; i < so.presets.Length; i++)
{
var p = so.presets[i];
float down = WL.CameraFraming.CameraFramingOverride.DownAngleDeg(p.cameraHeight, p.distance, p.distanceUp);
float above = WL.CameraFraming.CameraFramingOverride.CamHeightAbove(p.cameraHeight, p.distance, p.distanceUp);
float horiz = WL.CameraFraming.CameraFramingOverride.CamHorizontal(p.cameraHeight, p.distance);
L(string.Format(" [{0}] {1} pixelRig={2} h={3} d={4} up={5} ortho={6} pxH={7} → 내림각 {8:0.000}° · 높이 {9:0.000} m · 수평 {10:0.000} m",
i, p.name, p.pixelRig ? 1 : 0, p.cameraHeight, p.distance, p.distanceUp, p.orthoSize, p.pixelHeight, down, above, horiz));
}
// 도트A 프리셋 기준 캐릭터 픽셀
var d = so.presets.Length > 1 ? so.presets[1] : null;
if (d != null)
L(string.Format(" 도트A: orthoSize {0} · pixelHeight {1} → 월드 1 m = {2:0.000} px · 픽셀 1개 = {3:0.00000} m",
d.orthoSize, d.pixelHeight, d.pixelHeight / (2f * d.orthoSize), (2f * d.orthoSize) / d.pixelHeight));
}
// ── ② 프리팹 전수 ────────────────────────────────────────────────────────
static void Prefab(string path)
{
L("");
L("== ② 프리팹 " + path + " ==");
var go = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (go == null) { L(" 로드 실패"); return; }
var anim = go.GetComponentInChildren<Animator>(true);
L(" Animator = " + (anim == null ? "없음" : anim.gameObject.name));
if (anim != null)
{
L(" avatar = " + (anim.avatar == null ? "null" : anim.avatar.name + " · isHuman=" + anim.avatar.isHuman + " · isValid=" + anim.avatar.isValid));
L(" applyRootMotion = " + anim.applyRootMotion + " · cullingMode = " + anim.cullingMode);
var rac = anim.runtimeAnimatorController;
L(" controller = " + (rac == null ? "null" : rac.name + " (" + AssetDatabase.GetAssetPath(rac) + ")"));
if (rac != null)
{
var clips = rac.animationClips;
L(" clips = " + clips.Length);
var seen = new HashSet<string>();
foreach (var c in clips)
{
if (c == null || !seen.Add(c.name)) continue;
L(string.Format(" · {0,-28} len {1,6:0.000}s fps {2,5:0.#} frames {3,4} loop {4} legacy {5} hasMotion {6} hasRoot {7} empty {8}",
c.name, c.length, c.frameRate, Mathf.RoundToInt(c.length * c.frameRate), c.isLooping, c.legacy, c.hasMotionCurves, c.hasRootCurves, c.empty));
}
var ac = rac as UnityEditor.Animations.AnimatorController;
if (ac != null)
{
L(" layers = " + ac.layers.Length);
for (int li = 0; li < ac.layers.Length; li++)
{
var lay = ac.layers[li];
var sm = lay.stateMachine;
if (sm == null) { L(" layer[" + li + "] " + lay.name + " (stateMachine null)"); continue; }
var names = new List<string>();
foreach (var st in sm.states)
names.Add(st.state.name + "|" + (st.state.motion == null ? "-" : st.state.motion.name) + "|hash " + Animator.StringToHash(st.state.name)
+ "|full " + Animator.StringToHash(lay.name + "." + st.state.name));
L(" layer[" + li + "] " + lay.name + " · states " + names.Count + " · default=" + (sm.defaultState == null ? "-" : sm.defaultState.name));
foreach (var n in names) L(" " + n);
}
}
}
}
var smrs = go.GetComponentsInChildren<SkinnedMeshRenderer>(true);
var mrs = go.GetComponentsInChildren<MeshRenderer>(true);
L(" SkinnedMeshRenderer = " + smrs.Length + " · MeshRenderer = " + mrs.Length);
int tri = 0; var mats = new HashSet<string>();
foreach (var r in smrs)
{
if (r.sharedMesh != null) tri += r.sharedMesh.triangles.Length / 3;
foreach (var m in r.sharedMaterials) if (m != null) mats.Add(m.name + " [" + (m.shader == null ? "-" : m.shader.name) + "]");
}
foreach (var r in mrs)
{
var mf = r.GetComponent<MeshFilter>();
if (mf != null && mf.sharedMesh != null) tri += mf.sharedMesh.triangles.Length / 3;
foreach (var m in r.sharedMaterials) if (m != null) mats.Add(m.name + " [" + (m.shader == null ? "-" : m.shader.name) + "]");
}
L(" 삼각형 합계 = " + tri + " · 머티리얼 " + mats.Count + "종");
foreach (var m in mats) L(" " + m);
// 본 수
if (smrs.Length > 0 && smrs[0].bones != null) L(" bones[0] = " + smrs[0].bones.Length);
var allT = go.GetComponentsInChildren<Transform>(true);
L(" transform 노드 = " + allT.Length);
// 스케일·ClassConfig
L(" root localScale = " + go.transform.localScale.ToString("F4"));
foreach (var c in go.GetComponents<Component>())
if (c != null) L(" root comp: " + c.GetType().FullName);
// 인스턴스를 임시로 만들어 바운드 실측(씬 저장 0)
var inst = (GameObject)PrefabUtility.InstantiatePrefab(go);
try
{
inst.transform.position = Vector3.zero;
inst.transform.rotation = Quaternion.identity;
var b = WorldBounds(inst);
L(string.Format(" 바운드(스케일 1) center {0} size {1} · 높이 {2:0.0000} m", b.center.ToString("F4"), b.size.ToString("F4"), b.size.y));
inst.transform.localScale = Vector3.one * 0.7f;
var b7 = WorldBounds(inst);
L(string.Format(" 바운드(스케일 0.7) 높이 {0:0.0000} m · 폭 {1:0.0000} m · 깊이 {2:0.0000} m", b7.size.y, b7.size.x, b7.size.z));
}
finally { UnityEngine.Object.DestroyImmediate(inst); }
}
static Bounds WorldBounds(GameObject root)
{
var rs = root.GetComponentsInChildren<Renderer>(true);
bool any = false; var b = new Bounds();
foreach (var r in rs)
{
if (r == null || r is ParticleSystemRenderer) continue;
if (!any) { b = r.bounds; any = true; }
else b.Encapsulate(r.bounds);
}
return b;
}
// ── ③ 전 캐릭터 수 (확장 견적용) ────────────────────────────────────────
static void Counts()
{
L("");
L("== ③ 캐릭터 프리팹 수 (확장 견적 근거) ==");
var pc = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/Res_Addr/PC" });
var mob = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/Res_Addr/Mobs" });
L(" Res_Addr/PC 프리팹 = " + pc.Length);
L(" Res_Addr/Mobs 프리팹 = " + mob.Length);
int mobWithAnim = 0; var ctrls = new HashSet<string>();
foreach (var g in mob)
{
var p = AssetDatabase.GUIDToAssetPath(g);
var go = AssetDatabase.LoadAssetAtPath<GameObject>(p);
if (go == null) continue;
var a = go.GetComponentInChildren<Animator>(true);
if (a != null && a.runtimeAnimatorController != null) { mobWithAnim++; ctrls.Add(a.runtimeAnimatorController.name); }
}
L(" 그중 Animator+Controller 보유 = " + mobWithAnim + " · 서로 다른 컨트롤러 " + ctrls.Count + "종");
}
// ── ④ Toon 머티리얼 (814c) ──────────────────────────────────────────────
static void ToonMats()
{
L("");
L("== ④ 814c Toon 머티리얼 ==");
string dir = "Assets/WL/Look/Env/Materials";
var all = AssetDatabase.FindAssets("t:Material", new[] { dir });
L(" " + dir + " = " + all.Length + "개");
foreach (var key in new[] { "Ai_", "Batty" })
{
var hits = new List<string>();
foreach (var g in all)
{
var p = AssetDatabase.GUIDToAssetPath(g);
if (Path.GetFileName(p).StartsWith(key, StringComparison.OrdinalIgnoreCase)) hits.Add(Path.GetFileName(p));
}
L(" '" + key + "*' → " + hits.Count + "개: " + string.Join(", ", hits.ToArray()));
}
var envSo = Resources.Load<ScriptableObject>("WL/WLEnvLookSettings");
L(" WLEnvLookSettings = " + (envSo == null ? "없음" : "있음"));
}
}