В Unity 3D у меня есть MonoBehaviour
, который содержит список производных классов, все из которых основаны на общем ScriptableObject
.Список заполняется и обрабатывается в специальном редакторе.Это работает безупречно, но с одним исключением: всякий раз, когда я копирую / вставляю свой MonoBehaviour
или дублирую игровой объект, содержащий его в редакторе Unity, мой список содержит только экземпляры, а не уникальные клоны.
Вот несколько примеровкод (обратите внимание, что это только сокращенный тестовый код, мои классы намного сложнее, для чего требуется отдельный класс данных):
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public abstract class MyAbstractBaseClass : ScriptableObject
{
public abstract void foo();
}
public class MyTestScriptableObject : MyAbstractBaseClass
{
public string stringMember;
public override void foo()
{
}
}
public class MyTestMonoBehaviour : MonoBehaviour
{
public List<MyAbstractBaseClass> testList;
}
[CustomEditor(typeof(MyTestMonoBehaviour))]
public class MyTestMonoBehaviourEditor : Editor
{
const int NUM_LISTENTRIES = 5;
public override void OnInspectorGUI()
{
SerializedProperty testListProp = serializedObject.FindProperty("testList");
for (int i = 0; i < testListProp.arraySize; i++)
{
SerializedObject myTestScriptableObjectSO = new SerializedObject(testListProp.GetArrayElementAtIndex(i).objectReferenceValue);
SerializedProperty stringMemberProp = myTestScriptableObjectSO.FindProperty("stringMember");
EditorGUILayout.PropertyField(stringMemberProp);
myTestScriptableObjectSO.ApplyModifiedProperties();
}
if( GUILayout.Button("Generate List"))
{
testListProp.arraySize = NUM_LISTENTRIES;
for( int i=0; i<NUM_LISTENTRIES; i++)
testListProp.GetArrayElementAtIndex(i).objectReferenceValue = ScriptableObject.CreateInstance<MyTestScriptableObject>();
}
serializedObject.ApplyModifiedProperties();
}
}
Как я уже сказал, этот код работает без нареканий, за исключениемссылка / клон.Это означает, что когда я меняю строку 1 в GameObject A, строка 1 в скопированном GameObject B также изменяется.Конечно, я мог бы легко клонировать ScriptableObject
ссылки с ScriptableObject.Instantiate()
- моя проблема в том, что я не знаю, КОГДА клонировать.
Мои вопросы:
- существует ли какой-либо обратный вызов / виртуальный метод или аналогичный, который сообщает мне, когда мой
MonoBehaviour
дублируется в редакторе (через C & P или дублированные объекты GameObjects?) - В качестве альтернативы, есть ли какой-либо подсчет ссылок в C # или Unity-мудрый, который может сказать мне, как часто объект ссылается?Так как это всего лишь код редактора, метод, использующий отражение, тоже подойдет.
- Является ли
ScriptableObject
лучшим выбором для базы данных, которая должна быть уникальной вообще, или есть альтернативы?
Франкхермес уже предложил в комментариях использовать простые классы сериализованных данных.Это прекрасно работает для одного класса, но, к сожалению, не для иерархий классов с базовым классом, поскольку на самом деле они не поддерживаются в сериализации Unity.