// WL-814k 실측 조사 ③ — Humanoid/Generic 샘플링 경로 확정 (읽기만) // run: unity command run_script --file AgentScripts/WL814k_Survey3.cs --entry WL814k_Survey3.Run using System; using System.IO; using System.Text; using UnityEditor; using UnityEngine; public static class WL814k_Survey3 { const string kTxt = "AgentScripts/WL814k_SURVEY3.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")); try { Test("Assets/Res_Addr/PC/Ai01.prefab", new[] { "Idle", "Run", "Atk2_wing", "LightHit", "death_F3441" }); Test("Assets/Res_Addr/Mobs/Mob/Batty_A.prefab", new[] { "Idle", "Move", "Attack", "Damage", "Die" }); } catch (Exception ex) { L("EXCEPTION " + ex); } finally { if (AnimationMode.InAnimationMode()) AnimationMode.StopAnimationMode(); } File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false)); Debug.Log("[WL814k] → " + kTxt); } static void Test(string prefab, string[] clipNames) { L(""); L("== " + prefab + " =="); var src = AssetDatabase.LoadAssetAtPath(prefab); var inst = (GameObject)PrefabUtility.InstantiatePrefab(src); inst.transform.position = Vector3.zero; inst.transform.rotation = Quaternion.identity; try { var anim = inst.GetComponentInChildren(true); var rac = anim.runtimeAnimatorController; foreach (var name in clipNames) { AnimationClip clip = null; foreach (var c in rac.animationClips) if (c.name == name) { clip = c; break; } if (clip == null) { L(" " + name + " → 클립 없음"); continue; } // ⓐ AnimationMode 경로 float aSpread = Spread(inst, clip, true); // ⓑ clip.SampleAnimation 경로 float bSpread = Spread(inst, clip, false); L(string.Format(" {0,-14} len {1,5:0.00}s · AnimationMode Δbounds {2:0.0000} m · SampleAnimation Δbounds {3:0.0000} m", name, clip.length, aSpread, bSpread)); } } finally { if (AnimationMode.InAnimationMode()) AnimationMode.StopAnimationMode(); UnityEngine.Object.DestroyImmediate(inst); } } // 클립을 8등분해 찍고, 전체 렌더러 바운드 중심의 최대 이동량(= 실제로 포즈가 바뀌었는가) static float Spread(GameObject inst, AnimationClip clip, bool useAnimationMode) { var rs = inst.GetComponentsInChildren(true); Vector3 min = Vector3.positiveInfinity, max = Vector3.negativeInfinity; for (int i = 0; i < 8; i++) { float t = clip.length * i / 8f; if (useAnimationMode) { AnimationMode.StartAnimationMode(); AnimationMode.BeginSampling(); AnimationMode.SampleAnimationClip(inst, clip, t); AnimationMode.EndSampling(); AnimationMode.StopAnimationMode(); } else { clip.SampleAnimation(inst, t); } Bounds b = new Bounds(); bool any = false; foreach (var r in rs) { if (!any) { b = r.bounds; any = true; } else b.Encapsulate(r.bounds); } if (!any) continue; min = Vector3.Min(min, b.min); max = Vector3.Max(max, b.max); } if (float.IsInfinity(min.x)) return -1f; return (max - min).magnitude; } }