유니티 에디터에서 타입 목록이 필요한 경우가 있을 수 있습니다.
예를 들면 '특정 클래스를 상속한 ScriptableObject들을 자동으로 찾아서 에디터 메뉴(드롭다운 등)에서 선택해서 생성'을 만들고 싶다면 타입의 목록을 가져올 수 있어야 됩니다.
수동으로 구체화된 타입을 일일이 지정해 줄 것이 아니라면 보통 리플렉션을 활용하여 타입의 목록을 가져옵니다.
Unity 2019.2 이후 에디터에서는 타입 목록을 추출할 때 리플렉션 대신 TypeCache으로 대체가 가능합니다.
static List<Type> ScanInterfaceImplementors(Type interfaceType)
{
var types = new List<Type>();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
Type[] allAssemblyTypes;
try
{
allAssemblyTypes = assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
allAssemblyTypes = e.Types;
}
var myTypes = allAssemblyTypes.Where(t =>!t.IsAbstract && interfaceType.IsAssignableFrom(t));
types.AddRange(myTypes);
}
return types;
}
인터페이스를 구현한 타입을 찾는 코드입니다. 모든 타입을 찾아내고 인터페이스를 구현했는지 확인하고 있습니다.
이를 TypeCache로 대체하면 아래와 같습니다.
TypeCache.GetTypesDerivedFrom<MyInterface>().ToList()
코드가 더 간결해졌습니다.
static List<Type> ScanTypesWithAttributes(Type attributeType)
{
var types = new List<Type>();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
Type[] allAssemblyTypes;
try
{
allAssemblyTypes = assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
allAssemblyTypes = e.Types;
}
var myTypes = allAssemblyTypes.Where(t =>!t.IsAbstract && Attribute.IsDefined(t, attributeType, true));
types.AddRange(myTypes);
}
return types;
}
특정 Attribute가 붙은 타입들을 찾아내는 코드입니다.
이를 TypeCache로 대체하면 아래와 같습니다.
TypeCache.GetTypesWithAttribute<MyAttribute>().ToList();
마찬가지로 코드가 간결해졌습니다.
기존에는 리플렉션으로 모든 어셈블리를 순회하며 타입을 검사해야 했지만, TypeCache를 사용하면 훨씬 간결하고 직관적으로 가져올 수 있습니다.
구체적인 API는 작업 중이신 프로젝트 버전에 맞는 공식 문서를 확인하시면 됩니다.
https://docs.unity3d.com/ScriptReference/TypeCache.html
리플렉션은 런타임에 모든 어셈블리를 순회하며 타입 정보를 확인합니다. 따라서 도메인 리로드 시마다 타입을 다시 탐색하면 성능에 영향을 줄 수 있습니다.
반면, TypeCache는 네이티브에서 이미 캐싱 된 타입 정보를 활용하므로 훨씬 빠릅니다.
빈 프로젝트 기준으로 100 ms 이상을 절약하였음을 볼 수 있습니다.
실제로 크기가 큰 프로젝트에서 Stopwatch로 확인해 보았을 때 더 빠르게 동작을 했었습니다. (비공개 프로젝트라 이미지는 못 올립니다. 이 글을 읽으시는 분들은 적용해 보시면서 테스트해 보시는 걸 추천드립니다)
TypeCache가 UnityEditor 네임스페이스에 속해 있어 에디터 환경에서만 사용 가능하다는 점이 아쉽습니다.
그럼에도 불구하고, TypeCache는 리플렉션을 활용한 코드보다 더 간결하고 성능도 좋기에 에디터에서 사용하는 리플렉션 코드들을 대체할 만한 강점이 있다고 봅니다.