// WL-814k 진단 ④ — 루트 모션이 어느 트랜스폼에 실리는지 실측 // run: unity command run_script --file AgentScripts/WL814k_Diag4.cs --entry WL814k_Diag4.Run using System; using System.IO; using System.Text; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; public static class WL814k_Diag4 { const string kTxt = "AgentScripts/WL814k_DIAG4.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("HH:mm:ss")); Test("Assets/Res_Addr/PC/Ai01.prefab", new[] { "Run", "death_F3441" }); Test("Assets/Res_Addr/Mobs/Mob/Batty_A.prefab", new[] { "Move", "Die" }); File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false)); Debug.Log("[WL814k] → " + kTxt); } static void Test(string prefabPath, string[] clipNames) { GameObject pivot = null, inst = null; bool am = false; try { EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); var src = AssetDatabase.LoadAssetAtPath(prefabPath); pivot = new GameObject("Pivot"); inst = (GameObject)PrefabUtility.InstantiatePrefab(src); PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); inst.transform.SetParent(pivot.transform, false); inst.transform.localPosition = Vector3.zero; inst.transform.localRotation = Quaternion.identity; var anim = inst.GetComponent(); var rac = anim.runtimeAnimatorController; L(""); L("== " + prefabPath + " =="); var kids = new StringBuilder(); for (int i = 0; i < inst.transform.childCount; i++) kids.Append(inst.transform.GetChild(i).name + " "); L(" 직속 자식: " + kids); AnimationMode.StartAnimationMode(); am = true; foreach (var name in clipNames) { AnimationClip clip = null; foreach (var c in rac.animationClips) if (c.name == name) { clip = c; break; } if (clip == null) continue; var binds = AnimationUtility.GetCurveBindings(clip); var paths = new System.Collections.Generic.HashSet(); foreach (var b in binds) if (b.propertyName.StartsWith("m_LocalPosition")) paths.Add(b.path == "" ? "" : b.path); L(" 클립 " + name + " · 위치 커브가 걸린 경로 " + paths.Count + "개: " + string.Join(", ", new System.Collections.Generic.List(paths).ToArray())); for (int f = 0; f < 4; f++) { float t = clip.length * f / 4f; AnimationMode.BeginSampling(); AnimationMode.SampleAnimationClip(inst, clip, t); AnimationMode.EndSampling(); var sb = new StringBuilder(); sb.Append(string.Format(" f{0} rootLocal {1}", f, inst.transform.localPosition.ToString("F3"))); for (int i = 0; i < inst.transform.childCount; i++) { var ch = inst.transform.GetChild(i); sb.Append(" | " + ch.name + " " + ch.localPosition.ToString("F3")); } L(sb.ToString()); } } AnimationMode.StopAnimationMode(); am = false; } catch (Exception ex) { L("EXCEPTION " + ex); } finally { if (am && AnimationMode.InAnimationMode()) AnimationMode.StopAnimationMode(); if (pivot != null) UnityEngine.Object.DestroyImmediate(pivot); EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); } } }