[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.csusing 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.csusing 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 작법도 조사해 보세요.
Reference
이 문제에 관하여([Unity] 편집기 확장 및 유형 반사), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Egliss/items/4dc40c2d752e76e1d9c0
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
[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));
}
public static IEnumerable<Type> GetSubClasses(Type type)
{
var t = Assembly.GetAssembly(type)
.GetTypes()
.Where(m => m.IsSubclassOf(type) && !m.IsAbstract);
return t;
}
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; }
}
}
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>();
Reference
이 문제에 관하여([Unity] 편집기 확장 및 유형 반사), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Egliss/items/4dc40c2d752e76e1d9c0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)