Unity, несколько пользовательских редакторов для одного типа
Я делаю приложение C# на основе плагинов в Unity 5.6, где некоторые плагины могут иногда устанавливаться, иногда нет.
В моем плагине Plugin1
У меня есть компонент Plugin1.Component1
, В этом же проекте я реализую специальный редактор под названием Plugin1.Component1Editor
, это [CustomEditor(typeof(Plugin1.Component1))]
, когда Plugin1
установлен, Component1
доступно и отображается с помощью пользовательского редактора.
Мой плагин Plugin2
зависит от Plugin1
, В зависимости от настроек в его компоненте Plugin2.Component2
, он хотел бы изменить пользовательский редактор для Plugin1.Component1
,
Я реализовал новый пользовательский редактор в Plugin2
, называется Plugin2.Component1Editor
это тоже [CustomEditor(typeof(Plugin1.Component1))]
, Наследуется от UnityEditor.Editor
не из Plugin1.Component1Editor
, так как последний вызвал проблемы с сериализованными свойствами, не найденными в Plugin1.Component1Editor
,
Plugin2.Component1Editor
не столкнется с Plugin1.Component1Editor
во время компиляции, поскольку у него есть собственное пространство имен. Но что на самом деле происходит в Инспекторе Единства?
Поведение при тестировании - это желаемое поведение: Plugin2.Component1Editor
оказывает инспектора, если Plugin2
не установлено. Но почему? Я не хочу верить, что это будет продолжаться, если я не знаю почему.
Спасибо!
РЕДАКТИРОВАТЬ: я был неправ, это не рендеринг Plugin2.Component1Editor
, это был стандартный редактор Unity. Ни один из моих пользовательских редакторов не используется. Как я могу указать, какой из них я хочу использовать?
2 ответа
Кажется, что решение действительно было наследством.
Я сделал сериализованные свойства обработаны Plugin1.Component1Editor
и их поиск защищен вместо частного, а затем Plugin2.Component1Editor
наследуется от Plugin1.Component1Editor
вместо UnityEditor.Editor
, Тогда Plugin2.Component1Editor
стал рендерингом, называя Plugin1.Component1Editor
по мере необходимости.
Основной частью решения было то, что я сделал OnEnable
вызывать Plugin1.Component1Editor
, который извлекает сериализованные свойства, защищенные, чтобы я мог вызвать его из Plugin2.Component1Editor
с помощью base.OnEnable()
,
Для тех, кто натыкается на этот вопрос, решение OP работает (по крайней мере, для меня), только если у вас есть Plugin1 и Plugin2, где, как если бы у вас был Plugin3, последний плагин не будет загружен как настраиваемый редактор. Поэтому я придумал другое решение для этого.
Я решил использовать «Editor Hub», пользовательский редактор дляComponent1
, который ищетICustomEditor
реализации интерфейса с использованиемSystem.Reflection
, также в Unity есть хороший класс, напримерTypeCache
который может загрузить вам классы
public interface ICustomEditor
{
EditorType Type { get; }
void OnEnable(SerializedObject target);
void OnInspectorGUI(SerializedObject target);
}
Я решил пойти наEditorType.Before
илиEditorType.After
для визуализации пользовательских функций до или после основного редактора.
protected virtual void OnEnable()
{
CollectEditors();
OnEnableEditors();
}
public override void OnInspectorGUI()
{
OnInspectorGUIBefore();
base.OnInspectorGUI();
OnInspectorGUIAfter();
}
private void CollectEditors()
{
var types = TypeCache.GetTypesDerivedFrom(typeof(ICustomEditor));
var list = new List<ICustomEditor>();
foreach (var e in types)
{
var editor = (ICustomEditor)Activator.CreateInstance(e);
list.Add(editor);
}
m_beforeEditors = list
.Where(t => t.Type == EditorType.Before)
.ToArray();
m_afterEditors = list
.Where(t => t.Type == EditorType.After)
.ToArray();
}