// WL826_CtrlProbe.cs — 직업 컨트롤러의 공격 상태 전이(exitTime·duration)와 모션 길이 덤프 (에디터 · 읽기 전용) // unity command run_script --file AgentScripts/WL826_CtrlProbe.cs --entry WL826_CtrlProbe.Run --timeout 120 using System.Text; using UnityEditor; using UnityEditor.Animations; using UnityEngine; public static class WL826_CtrlProbe { static readonly string[] Ctrls = { "onehand", "spellblade", "bluntshield", "paladin", "assassin", "bladedancer", "archer", "rookiearcher", "mage", "sorceress", "summoner", "spear" }; public static string Run() { var sb = new StringBuilder(); foreach (var c in Ctrls) { var path = "Assets/Res_Addr/Animations/pcanim_" + c + ".controller"; var ctrl = AssetDatabase.LoadAssetAtPath(path); if (ctrl == null) { sb.Append(c).Append(": 없음\n"); continue; } sb.Append("== ").Append(c).Append('\n'); foreach (var cs in ctrl.layers[0].stateMachine.states) { var st = cs.state; bool atk = st.name.ToLower().Contains("attack"); if (!atk) continue; var clip = st.motion as AnimationClip; sb.Append(" ").Append(st.name).Append(" motion=").Append(clip != null ? clip.name + "(" + clip.length.ToString("0.00") + "s)" : (st.motion != null ? st.motion.name : "-")).Append(" speed=").Append(st.speed.ToString("0.##")); foreach (var t in st.transitions) sb.Append(" | →").Append(t.destinationState != null ? t.destinationState.name : (t.isExit ? "Exit" : "?")).Append(" exit=").Append(t.hasExitTime ? t.exitTime.ToString("0.00") : "no").Append(" dur=").Append(t.duration.ToString("0.00")).Append(t.conditions.Length > 0 ? " cond" : ""); sb.Append('\n'); } foreach (var t in ctrl.layers[0].stateMachine.anyStateTransitions) if (t.destinationState != null && t.destinationState.name.ToLower().Contains("attack")) sb.Append(" Any→").Append(t.destinationState.name).Append(" exit=").Append(t.hasExitTime ? t.exitTime.ToString("0.00") : "no").Append(" dur=").Append(t.duration.ToString("0.00")).Append('\n'); } return sb.ToString(); } }