Динамическое создание класса CustomEditor в Unity / C#
Я пытаюсь реализовать сценарии режима редактирования в моем проекте Unity. Идея состоит в том, что сценарий может быть присоединен к объекту, и по мере его редактирования атрибуты, такие как масштаб / положение / поворот, могут быть обновлены.
Без написания сценария режима редактирования все это возможно, но изменения не видны, пока не нажата кнопка воспроизведения. В этом разница.
Я использую вариант скрипта, предоставленного здесь, чтобы сделать это.
Прежде всего, к моему игровому объекту прикреплен скрипт MonoBehavior - он выглядит так:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class FlippersEditMode : MonoBehaviour {
public float extraScale = 1f;
public void updateEditorState() {
transform.localScale = (Vector3.up * extraScale);
}
}
Во-вторых, у меня есть скрипт в папке редактора, который вызывает это updateEditorState
метод всякий раз, когда нажимается кнопка "Обновить":
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(FlippersEditMode))]
public class FlipperEditModeMeta: Editor {
public override void OnInspectorGUI() {
base.OnInspectorGUI();
if (GUILayout.Button("Update")) {
if (target.GetType() == typeof(FlippersEditMode)) {
FlippersEditMode flippers = (FlippersEditMode)target;
flippers.updateEditorState();
}
}
}
}
Это прекрасно работает, и я благодарен за это, но этот последний кусок кода является чистым шаблоном. Мне нужно будет иметь почти идентичный один из этих файлов для каждого скрипта, который я хочу использовать в режиме редактирования.
Поэтому я начал пытаться сделать сценарий редактора "meta". Идея состоит в том, что этот скрипт будет иметь массив слотов, в которые разработчик может перетаскивать скрипты. Каждый скрипт, перетащенный сюда, получит класс CustomEditor, определенный как тот, который показан выше. Конечно, перетаскиваемые здесь классы должны быть реализованы updateEditorState
но это единственное требование протокола.
Так что, если я сделаю другой редактор сценарий, который выглядит следующим образом:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(EditModeScripts))]
public class EditModeScriptsMeta : Editor {
public override void OnInspectorGUI() {
base.OnInspectorGUI();
if (GUILayout.Button("Update")) {
if (target.GetType() == typeof(EditModeScripts)) {
EditModeScripts edit_mode_scripts = (EditModeScripts)target;
edit_mode_scripts.updateEditorState()
}
}
}
}
Тогда я могу вызвать updateEditorState
функция в следующем:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class EditModeScripts : MonoBehaviour {
public MonoBehaviour[] scripts = {};
public void updateEditorState () {
for (int i = 0; i < scripts.Length; i++) {
MonoBehaviour script = scripts[i];
// How to generate an editor class here for each script?
}
}
}
Но, как вы можете видеть, я не знаю, как динамически генерировать классы.
1 ответ
Я не думаю, что ваш подход будет работать чисто динамически. Unity компилирует ваш код каждый раз, когда вы что-то меняете и возвращаетесь к единству. После компиляции Unity использует Reflection, чтобы определить, какие редакторы доступны.
Вы можете теоретически создать новые исходные файлы, которые содержат код редактора. Однако я не знаю, будет ли он автоматически импортировать сценарии или вам нужно вручную инициировать повторный импорт.
Для ручного импорта вы можете использовать комбинацию AssetDatabase.Refresh()
и если этого недостаточно, выберите актив скрипта через Selection
класс и вызвать пункт меню reimport, используя EditorApplication.ExecuteMenuItem
,