EditorWindow и SerializedObject.ApplyModifiedProperties(). Как избавиться от ошибки "SerializedObject target has been destroyed"
Имею несколько окошек редактора в которых через диалоги задаю значение свойства. Диалоги большие, с кучей вложенных свойств. В целом работа с окошком выглядит примерно вот так:
using UnityEngine;
using UnityEditor;
public class MyEditorWindow : EditorWindow
{
[MenuItem("Window/My Editor Window")]
public static void ShowWindow()
{
GetWindow<MyEditorWindow>();
}
// список свойств окна к изменению
public string[] Strings = { "Larry", "Curly", "Moe" };
// ссылка на сериализованный объект где будут наши свойства окна
SerializedObject so;
private void OnEnable()
{
//здесь инициируем объект
so = new SerializedObject(this);
}
void OnGUI()
{
so.Update();
//дальше выводим нужный интерфейс через EditorGUILayout, а ля
SerializedProperty stringsProperty = so.FindProperty("Strings");
EditorGUILayout.PropertyField(stringsProperty, true);
so.ApplyModifiedProperties(); // Вот здесь периодически и падает ошибка
}
}
Через поиск встречал, что существует проблема с тем, что при потере фокуса объекта в сцене, а также перехода между диалоговыми окнами в точке где идет обновление свойств объекта so.ApplyModifiedProperties();
частенько редактор генерирует ошибку
SerializedObject target has been destroyed
пробовал заключать отрисовку в BeginChange
и EndChange
, но это не спасает. На целостность данных в диалогах вроде это не влияет, но раздражает.
Кто-то знает как с этим бороться?
Ответы (2 шт):
Вообще разработчики не хотят что-бы кто-то сам создавал SerializedObject
и в документации даже нет описания его свойств, кто такие inspectorMode
или inspectorDataMode
, которые указываются в Editor.cs
... ну хер его знает. Уж тем более писал такую порнуху как new SerializedObject(this)
точно никто не предусматривал и бороться тут не с чем.
SerializedObject
стримит данные и является IDisposable
и за его жизненным циклом нужно следить. Это прописано в классе Editor
, у которого есть target
для которого создаётся и уничтожается SerializedObject
. При использовании в инспекторе, target
присваивается автоматически в контексте выбранного объекта, но можно легко делать это и в ручную, если речь не о инспекторе.
По идее и вообще по принципам программирования, модели данных должны быть отделены от визуализации. То есть массив не должен быть среди полей EditorWindow
, потому что окно выступает в роли view. В EditorWindow
нужно выстраивать композицию из набора Editor
просто вызывая их OnGUI
и используя EditorGUI
по мелочи.
Нашел причину, из-за чего появлялась ошибка. Внутри OnGUI выводился интерфейс и была кнопочка по которой обновлялось свойство в родительском окне и собственно само диалоговое окно закрывалось. Получалось что окно закрыто, но OnGUI еще дорисовывает интерфейс диалога которого нет.
Так что все, что требовалось - это вызывать процедуру закрытия окна после того как интерфейс будет отрисован и отработает so.ApplyModifiedProperties();