유니티 애니메이션 작업 중, 애니메이션 트랜지션 연결 작업은 굉장히 단순하지만, 반복적인 작업일 것입니다.
트래지션 연결과 변수 세팅.
혹여, 애니메이션 간의 연결에 미처 누락이라도 생긴다면 예기치 못한 에러를 일으킬 수도 있죠.
이러한 에러와 반복작업의 횟수를 줄이고자, 애니메이션 트랜지션 연결을 자동화로 해결할 수 있는 툴을 만들었습니다.
애니메이션 트랜지션을 생성할 객체를 하이어라키에서 생성합니다.
이때, 선택한 객체에는 애니메이터가 있어야 합니다.
컨트롤러 변수는, 애니메이터에서 미리 동일한 이름으로 생성해주어야 합니다.
애니메이션 자동화 버튼을 누르면, 상단의 그림과 같이, 자신을 제외한 모든 객체와 트랜지션을 연결했음을 확인할 수 있습니다.
Act9 애니메이션의 트랜지션 상태입니다.
트랜지션의 연결은 성공적으로 구현했으나,
각 트랜지션 간의 변수 세팅은 올바르게 구현하지 못했습니다.
즉, 고유의 id값처럼 자기자신을 가리키는 제어 변수 값이 제대로 설정되지 않았습니다.
각 트랜지션 당, 딕셔너리로 파라미터를 할당하여 고유 값을 가지도록 구현했습니다.
또한 모든 트랜지션을 한번에 제거할 수 있는 버튼도 추가했습니다.
using UnityEditor;
using UnityEngine;
using UnityEditor.Animations;
using System.Collections.Generic;
public class ECN_AnimationSetupWindow : EditorWindow
{
// 각 스테이트에 대한 파라미터 값을 저장할 딕셔너리
public Dictionary<AnimatorState, int> stateMatchValue = new Dictionary<AnimatorState, int>();
int parameter = 0;
// 사용자가 입력할 파라미터의 이름
public string parameterName = "MyIntParameter";
[MenuItem("Tools/ECN_AnimationConnectAutometic")]
public static void ShowWindow()
{
GetWindow(typeof(ECN_AnimationSetupWindow), false, "Animation Setup");
}
void OnGUI()
{
GUILayout.Label("애니메이션 설정", EditorStyles.boldLabel);
parameter = 0;
stateMatchValue.Clear();
// 커스텀 창에서 사용자가 parameterName을 입력할 수 있도록 TextField 추가
parameterName = EditorGUILayout.TextField("Parameter Name", parameterName);
if (GUILayout.Button("애니메이션 설정 자동화"))
{
AutomateAnimationSetup();
}
if (GUILayout.Button("모든 트랜지션 제거"))
{
RemoveAllTransitions();
}
}
void AutomateAnimationSetup()
{
// 선택한 객체의 애니메이터 가져오기
Animator animator = Selection.activeGameObject.GetComponent<Animator>();
if (animator != null)
{
// Animator Controller 가져오기
AnimatorController controller = animator.runtimeAnimatorController as AnimatorController;
if (controller != null)
{
int uniqueParameter = 0; // 시작 값 설정
// 각 애니메이션 클립에 대한 설정 수행
foreach (AnimatorControllerLayer layer in controller.layers)
{
foreach(ChildAnimatorState state in layer.stateMachine.states)
{ // 각 스테이트에 파라미터를 할당.
AnimatorState animatorState = state.state;
stateMatchValue.Add(animatorState, parameter);
parameter++;
}
foreach (ChildAnimatorState state in layer.stateMachine.states)
{
AnimatorState animatorState = state.state;
// 자기 자신을 제외한 다른 상태들과 트랜지션 설정
foreach (ChildAnimatorState otherState in layer.stateMachine.states)
{
AnimatorState otherAniState = otherState.state;
if (otherState.state != animatorState)
{
// 각 트랜지션에 대한 고유한 파라미터 값 설정
int currentUniqueParameter = stateMatchValue[otherAniState];
// 트랜지션과 파라미터를 딕셔너리에 추가
AddTransitionWithParameter(animatorState, otherAniState, parameterName, currentUniqueParameter);
}
}
uniqueParameter++;
}
}
Debug.Log("Animation Setup Completed!");
}
else
{
Debug.LogError("No Animator Controller found on the selected object.");
}
}
else
{
Debug.LogError("No Animator component found on the selected object.");
}
}
AnimatorStateTransition AddTransitionWithParameter(AnimatorState sourceState, AnimatorState destinationState, string parameterName, int parameterValue)
{
// 트랜지션 생성 및 설정
AnimatorStateTransition transition = sourceState.AddTransition(destinationState);
// 파라미터 조건 추가 (인트형 파라미터 설정)
transition.AddCondition(AnimatorConditionMode.Equals, parameterValue, parameterName);
return transition;
}
// 모든 트랜지션 제거
void RemoveAllTransitions()
{
// 선택한 객체의 애니메이터 가져오기
Animator animator = Selection.activeGameObject.GetComponent<Animator>();
if (animator != null)
{
// Animator Controller 가져오기
AnimatorController controller = animator.runtimeAnimatorController as AnimatorController;
if (controller != null)
{
// 각 레이어에 대한 처리
foreach (AnimatorControllerLayer layer in controller.layers)
{
// 각 스테이트에 대한 처리
foreach (ChildAnimatorState state in layer.stateMachine.states)
{
// 해당 스테이트의 트랜지션 제거
RemoveTransitions(state.state);
}
}
Debug.Log("All Transitions Removed!");
}
else
{
Debug.LogError("No Animator Controller found on the selected object.");
}
}
else
{
Debug.LogError("No Animator component found on the selected object.");
}
parameter = 0;
stateMatchValue.Clear();
}
void RemoveTransitions(AnimatorState state)
{
// 해당 스테이트의 모든 트랜지션 가져오기
AnimatorStateTransition[] transitions = state.transitions;
// 각 트랜지션 제거
foreach (AnimatorStateTransition transition in transitions)
{
state.RemoveTransition(transition);
}
}
}