63 lines
3.8 KiB
C#
63 lines
3.8 KiB
C#
// WL884_Anim.cs — PD 지시 #884 칼날 폭풍 다듬기: 힘민지 양손검의 「시작 → 회전 반복」 상태 사슬을 다른 컨트롤러로 옮긴다 (에디터 · Play 아님)
|
|
// unity command run_script --file AgentScripts/WL884_Anim.cs --entry WL884_Anim.CopyChain --args '[src컨트롤러, 시작 상태, dst컨트롤러, 새 반복 상태 이름]'
|
|
// 반복 상태는 나가는 전이가 없다(원본과 같음) — 스킬 투사체(Skill_Whirlwind)가 지속시간 끝에 Play_Idle 로 끝낸다.
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.Animations;
|
|
using UnityEngine;
|
|
|
|
public static class WL884_Anim
|
|
{
|
|
static AnimatorState FindIn(AnimatorStateMachine sm, string name, out AnimatorStateMachine owner)
|
|
{
|
|
foreach (var cs in sm.states) if (cs.state.name == name) { owner = sm; return cs.state; }
|
|
foreach (var sub in sm.stateMachines) { var r = FindIn(sub.stateMachine, name, out owner); if (r != null) return r; }
|
|
owner = null; return null;
|
|
}
|
|
|
|
static AnimatorState Find(UnityEditor.Animations.AnimatorController c, string name, out AnimatorStateMachine owner)
|
|
{
|
|
owner = null;
|
|
foreach (var l in c.layers) { var s = FindIn(l.stateMachine, name, out owner); if (s != null) return s; }
|
|
return null;
|
|
}
|
|
|
|
static void CopyTransition(AnimatorStateTransition t, AnimatorStateTransition nt)
|
|
{
|
|
nt.hasExitTime = t.hasExitTime; nt.exitTime = t.exitTime; nt.duration = t.duration; nt.hasFixedDuration = t.hasFixedDuration; nt.offset = t.offset;
|
|
nt.interruptionSource = t.interruptionSource; nt.orderedInterruption = t.orderedInterruption; nt.canTransitionToSelf = t.canTransitionToSelf;
|
|
foreach (var cnd in t.conditions) nt.AddCondition(cnd.mode, cnd.threshold, cnd.parameter);
|
|
}
|
|
|
|
public static object CopyChain(string srcCtrl, string startState, string dstCtrl, string loopName)
|
|
{
|
|
var src = AssetDatabase.LoadAssetAtPath<UnityEditor.Animations.AnimatorController>(srcCtrl);
|
|
var dst = AssetDatabase.LoadAssetAtPath<UnityEditor.Animations.AnimatorController>(dstCtrl);
|
|
if (src == null || dst == null) return "컨트롤러 없음";
|
|
AnimatorStateMachine so, dso, lo;
|
|
var s0 = Find(src, startState, out so);
|
|
var d0 = Find(dst, startState, out dso);
|
|
if (s0 == null || d0 == null) return "시작 상태 없음 " + startState;
|
|
var st = s0.transitions.FirstOrDefault(t => t.destinationState != null);
|
|
if (st == null) return "원본 시작 상태에 다음 상태 전이 없음";
|
|
var s1 = st.destinationState;
|
|
if (s1.transitions.Length > 0) return "원본 반복 상태에 나가는 전이 " + s1.transitions.Length + "개 — 이 도구 범위 밖(중단)";
|
|
|
|
var d1 = Find(dst, loopName, out lo);
|
|
bool created = d1 == null;
|
|
if (created) d1 = dso.AddState(loopName, dso.states.First(x => x.state == d0).position + new Vector3(260f, 0f, 0f));
|
|
d1.motion = s1.motion; d1.speed = s1.speed; d1.tag = s1.tag; d1.writeDefaultValues = s1.writeDefaultValues; d1.iKOnFeet = s1.iKOnFeet; d1.mirror = s1.mirror;
|
|
d1.speedParameterActive = s1.speedParameterActive; d1.speedParameter = s1.speedParameter;
|
|
foreach (var t in d1.transitions.ToArray()) d1.RemoveTransition(t);
|
|
|
|
int removed = d0.transitions.Length;
|
|
foreach (var t in d0.transitions.ToArray()) d0.RemoveTransition(t);
|
|
CopyTransition(st, d0.AddTransition(d1));
|
|
|
|
EditorUtility.SetDirty(dst);
|
|
AssetDatabase.SaveAssets();
|
|
return (created ? "추가 " : "갱신 ") + loopName + " ← " + s1.name + "(" + AssetDatabase.GetAssetPath(s1.motion) + " · 속도 " + s1.speed + ") · " + startState + " 전이 " + removed + "개 → " + loopName
|
|
+ " exit " + st.exitTime.ToString("F2") + " · 전환 " + st.duration.ToString("F2") + (st.hasFixedDuration ? "s" : "n");
|
|
}
|
|
}
|