[Unity] 편집기 확장 및 유형 반사

13257 단어 UnityEditorUnityC#

편집기 확장 및 유형 반사


주의


이 글에는 반사를 수행할 때 사용하는 것을 전제로 한 내용이 담겨 있다.
훈련된 엔지니어가 실행할 때 반사를 하려면 거부 반응이 나타날 수 있으니 주의하세요.

개요


갑자기 C#가 반사되는 언어라는 생각이 들었어요.
편집기와 확장해서 조합할 수 있는지 시험해 보세요.
[SerializeField]
[ReflectionSubClassPopup(typeof(CharacterAction),true)]
private List<string> _actionTypeNameList = new List<string>();
public IReadOnlyCollection<string> ActionTypeNameList  
{ 
    get { return _actionTypeNameList; } 
}
이것 괜찮아요?
foreach(var item in ActionTypeNameList){
    this.AddComponent(Type.GetType(item));
}
그래서 부품을 추가하고 싶은 경우도 있다.
갑자기 떠오르는 것은 Editor GUI입니다.특정 학급에서 파생된 클래스는 팝업에 열거할 수 없습니다.

리플렉스


어쨌든 파생류를 얻는 코드부터 작성해.
public static IEnumerable<Type> GetSubClasses(Type type)
{
    var t = Assembly.GetAssembly(type)
        .GetTypes()
        .Where(m => m.IsSubclassOf(type) && !m.IsAbstract);
    return t;
}
생각보다 쉽게 구할 수 있어요.
추가 매개 변수가 IsAbstract 판정 등을 진행할지 여부라면 상당히 편리한 함수가 된다.
이 함수를 편집기 확장자와 조합합니다.

편집기 확장


먼저 속성 정의
ReflectionSubClassPopupAttribute.cs
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Egliss
{
    public class ReflectionSubClassPopupAttribute: PropertyAttribute 
    {
        public ReflectionSubClassPopupAttribute(Type t, bool isNothingable = false)
        {
            this.type = t;
            this.isNothingable = isNothingable;
        }
        public Type type { get; private set; }
        public bool isNothingable { get; private set; }
    }
}
그런 다음 해당 속성에 맞는 PropertyDrawer를 정의합니다.
ReflectionSubClassPopupDrawer.cs
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using System.Reflection;

namespace Egliss.Editors
{
    [CustomPropertyDrawer(typeof(ReflectionSubClassPopupAttribute))]
    public class ReflectionSubClassPopupDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var atr = this.attribute as ReflectionSubClassPopupAttribute;
            var types = EditorHelper.GetSubClasses(atr.type).Select(m => m.FullName).ToList();
            var index = types.FindIndex(m => m == property.stringValue);

            //add nothing
            if (atr.isNothingable)
            {
                types.Insert(0, "Nothing");
                index++;
            }
            if (types.Count == -1)
            {
                var typeName = Assembly.GetAssembly(atr.type).FullName;
                EditorGUI.LabelField(position, typeName + "'s subclass not found...");
                return;
            }

            //type string missing
            if(index == -1)
                index = 0;

            property.stringValue = types[EditorGUI.Popup(position, label.text, index, types.ToArray())];
        }
    }
}
이렇게 하면 준비할 수 있어요!

결실


변수에 속성 추가 실제 보기 검사자

[SerializeField]
[ReflectionSubClassPopup(typeof(CharacterAction), true)]
private string _actionTypeName;

확인이 순조롭게 열거되다.
그리고 리스트에서도 이거에 대응하려고...
[SerializeField]
[ReflectionSubClassPopup(typeof(CharacterAction),true)]
private List<string> _actionList = new List<string>();
이것이 바로

이렇게 표시됐습니다.
속성은 리스트 자체가 아니라 리스트의 요소...
이번 의 목적 은 이러 한 행위 이기 때문에 너무 깊이 따지지 않겠다
기분이 좋으면 리스트의Property Drawer 작법도 조사해 보세요.

좋은 웹페이지 즐겨찾기