프리팹에는 애니메이터가 부착되어 있고,
애니메이터를 제어하기 위해서는 특정 파라미터가 필요합니다.
하지만 모든 프리팹 객체의 파라미터를 일일히 생성하는 행위는 굉장히 번거롭고
반복적인 행동입니다.
자동화 툴을 구현하여, 특정 디렉토리 path 이하의 모든 폴더와 객체를 탐색하면서
프리팹을 저장하고 프리팹이 가지고 있는 Animator 컴포넌트를 Get하여, 파라미터를 자동으로 생성하면 좋겠다는 필요성을 느꼈습니다.
OnGUI 함수
에디터 창의 GUI를 구성하는 함수입니다.
선택한 폴더의 경로를 입력할 수 있는 텍스트 필드와 폴더를 선택할 수 있는 버튼을 제공합니다.
Add Cmd to Animators 버튼을 클릭하면 선택한 폴더 내의 프리팹에 대해 파라미터 추가 작업을 시작합니다.
AddCmdToAnimatorsInFolder 함수
주소의 유효성을 검사합니다. 이후 TraverseFolderForAnimators 함수를 호출하여 하위 폴더의 모든 프리팹을 List에 저장합니다.
리스트에 있는 모든 GameObject들에 대해 AddCmdToAnimator 함수를 호출하여 'cmd' 파라미터를 추가합니다.
TraverseFolderForAnimators 함수
주어진 폴더 경로에서 모든 파일과 하위 폴더를 재귀적으로 탐색합니다.
각 파일이 프리팹인지 확인하고, 프리팹인 경우 ProcessFile 함수를 호출합니다.
ProcessFile 함수
파일 경로를 받아 프리팹인지 확인하고, 프리팹이면 해당 프리팹을 로드합니다.
프리팹 내에 Animator 컴포넌트가 있는지 확인하고, 있다면 결과 리스트에 추가합니다.
AddCmdToAnimator 함수
주어진 GameObject 내의 모든 Animator에 대해 'cmd'라는 정수형 파라미터가 있는지 확인합니다.
해당 파라미터가 없으면 Animator Controller에 'cmd' 파라미터를 추가합니다.
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using System.Collections.Generic;
using System.Collections;
using System;
using System.IO;
public class AddCmdToIntAnimator : EditorWindow
{
private string selectedFolderPath;
private bool processing;
[MenuItem("Tools/Add Cmd to Animator", false, 0)]
static void Init()
{
// 기존에 열려있는 창을 가져오거나, 없으면 새 창을 만듭니다:
AddCmdToIntAnimator window = (AddCmdToIntAnimator)EditorWindow.GetWindow(typeof(AddCmdToIntAnimator));
window.Show();
}
void OnGUI()
{
GUILayout.Label("'cmd' int 파라미터를 추가할 프리팹이 저장된 폴더를 선택하세요:");
EditorGUILayout.BeginHorizontal();
selectedFolderPath = EditorGUILayout.TextField("선택된 폴더", selectedFolderPath);
if (GUILayout.Button("폴더 선택", GUILayout.Width(100)))
{
string tempFolderPath = EditorUtility.OpenFolderPanel("폴더 선택", selectedFolderPath, "");
if (!string.IsNullOrEmpty(tempFolderPath))
{
selectedFolderPath = tempFolderPath;
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(20);
EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(selectedFolderPath) || processing);
if (GUILayout.Button("애니메이터에 Cmd 추가"))
{
AddCmdToAnimatorsInFolder(selectedFolderPath);
}
EditorGUI.EndDisabledGroup();
}
void AddCmdToAnimatorsInFolder(string folderPath)
{
if (string.IsNullOrEmpty(folderPath) || !Directory.Exists(folderPath))
{
Debug.LogWarning("잘못된 폴더 경로이거나 폴더가 존재하지 않습니다.");
return;
}
processing = true;
List<GameObject> objectsWithAnimator = new List<GameObject>();
TraverseFolderForAnimators(folderPath, objectsWithAnimator);
foreach (var obj in objectsWithAnimator)
{
AddCmdToAnimator(obj);
}
processing = false;
}
void TraverseFolderForAnimators(string folderPath, List<GameObject> result)
{
// 현재 폴더의 모든 파일을 가져옵니다.
string[] files = Directory.GetFiles(folderPath);
foreach (string file in files)
{
ProcessFile(file, result);
}
// 각 하위 디렉토리를 재귀적으로 탐색합니다.
string[] subdirectories = Directory.GetDirectories(folderPath);
foreach (string directory in subdirectories)
{
TraverseFolderForAnimators(directory, result);
}
}
void ProcessFile(string filePath, List<GameObject> result)
{
// 파일이 프리팹인지 확인하고, 프리팹인 경우 처리합니다.
if (filePath.EndsWith(".prefab"))
{
string assetPath = "Assets" + filePath.Substring(Application.dataPath.Length);
GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
if (obj != null)
{
Animator animator = obj.GetComponentInChildren<Animator>();
if (animator != null && !result.Contains(obj))
{
result.Add(obj);
}
}
}
}
void AddCmdToAnimator(GameObject obj)
{
Animator[] animators = obj.GetComponentsInChildren<Animator>(true);
foreach (var animator in animators)
{
AnimatorController animatorController = animator.runtimeAnimatorController as AnimatorController;
if (animatorController != null)
{
bool parameterExists = false;
AnimatorControllerParameter[] parameters = animatorController.parameters;
foreach (var param in parameters)
{
if (param.name == "cmd" && param.type == AnimatorControllerParameterType.Int)
{
parameterExists = true;
break;
}
}
if (!parameterExists)
{
animatorController.AddParameter("cmd", AnimatorControllerParameterType.Int);
Debug.Log("GameObject에 있는 Animator에 'cmd' int 파라미터를 추가했습니다: " + animator.gameObject.name);
}
}
}
}
}