我有以下可脚本化的对象:
[CreateAssetMenu(fileName = "Assets/Gladio Games/Resources/Levels/LEVLE_TMP", menuName = "Utils/Crossword/Generate Empty Level", order = 100)]
public class Level : ScriptableObject
{
public char[,] Table { get; protected set; }
public List<Crossword> Crosswords { get; protected set; }
protected static char EMPTY_CHAR = ' ';
public Crossword GetCrosswordAtIndex(int x, int y, Direction direction)
{
//Ottieni la prima e l'unica parola che si trova sotto quell'indice
return Crosswords.First(crossword => crossword.Direction == direction && crossword.GetCrosswordIndexes().Contains(new Vector2(x, y)));
}
}
这是我用来保存Scriptable Object
的代码private static void Save(Level level, string path)
{
EditorUtility.SetDirty(level);
AssetDatabase.CreateAsset(level, path + ".asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
对象是通过编辑器脚本成功创建的,它保存了所有数据,但如果我关闭并重新打开编辑器,并尝试加载字段为空。用于保存和加载可脚本对象的脚本在场景
中使用。我做错了什么?
检查脚本序列化规则
特别是在你的情况下
-
Unity中的序列化器直接作用于字段c#类而不是它们的属性,因此您的字段必须符合一些规则才能序列化。
-
注意:Unity不支持多层类型的序列化(多维数组)、锯齿数组、字典和嵌套容器类型)
所以你的属性没有序列化(=已保存)
作为解决方案
-
For
Crosswords
-
确保类型
Crossword
本身为[Serializable]
-
使用字段而不是
public List<Crossword> Crosswords;
-
-
对于
Table
有多种途径我可能会简单地使用一个包装类,例如
// Could of course make this generic but for the drawer it easier this way for now [Serializable] public class Table { [SerializeField] [Min(1)] private int xDimension = 1; [SerializeField] [Min(1)] private int yDimension = 1; [SerializeField] private char[] flatArray = new char[1]; public Table() { } public Table(char[,] array) { xDimension = array.GetLength(0); yDimension = array.GetLength(1); flatArray = new char[xDimension * yDimension]; for (var x = 0; x < xDimension; x++) { for (var y = 0; y < yDimension; y++) { flatArray[x * yDimension + y] = array[x, y]; } } } public Table(int x, int y) { xDimension = x; yDimension = y; flatArray = new char[x * y]; } public Table(char[] array, int x, int y) { xDimension = x; yDimension = y; flatArray = array; } public char this[int x, int y] { get => flatArray[x * yDimension + y]; set => flatArray[x * yDimension + y] = value; } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(Table))] private class TableDrawer : PropertyDrawer { private const int k_elementSpacing = 5; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { var height = 1f; if (property.isExpanded) { height += property.FindPropertyRelative(nameof(Table.xDimension)).intValue * 1.5f; } return height * EditorGUIUtility.singleLineHeight; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { var foldoutRect = position; foldoutRect.height = EditorGUIUtility.singleLineHeight; foldoutRect.width = EditorGUIUtility.labelWidth; property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label); if (property.isExpanded) { var xRect = position; xRect.height = EditorGUIUtility.singleLineHeight; xRect.x += foldoutRect.width; xRect.width -= foldoutRect.width; xRect.width *= 0.5f; var yRect = xRect; yRect.x += xRect.width; var xDimension = property.FindPropertyRelative(nameof(Table.xDimension)); var yDimension = property.FindPropertyRelative(nameof(Table.yDimension)); var array = property.FindPropertyRelative(nameof(Table.flatArray)); using (var changeCheck = new EditorGUI.ChangeCheckScope()) { EditorGUI.PropertyField(xRect, xDimension, GUIContent.none); EditorGUI.PropertyField(yRect, yDimension, GUIContent.none); if (changeCheck.changed) { array.arraySize = xDimension.intValue * yDimension.intValue; } } position.y += EditorGUIUtility.singleLineHeight * 1.5f; EditorGUI.indentLevel++; var elementRect = EditorGUI.IndentedRect(position); EditorGUI.indentLevel--; var elementWidth = elementRect.width / yDimension.intValue - k_elementSpacing; var elementHeight = EditorGUIUtility.singleLineHeight; var currentPosition = elementRect; currentPosition.width = elementWidth; currentPosition.height = elementHeight; for (var x = 0; x < xDimension.intValue; x++) { for (var y = 0; y < yDimension.intValue; y++) { var element = array.GetArrayElementAtIndex(x * yDimension.intValue + y); EditorGUI.PropertyField(currentPosition, element, GUIContent.none); currentPosition.x += elementWidth + k_elementSpacing; } currentPosition.x = elementRect.x; currentPosition.y += elementHeight * 1.5f; } } } } #endif }
然后rather有e.g.
public Table Table;