Serialize custom multidimensional array from Inspector

I made this custom script Editor for a multidimensional array but I can’t serialize it. Any change I made to the array will automatically reset on Play. How can I serialize the custom array setup from the Inspector?

113768-multi-array2.png

Levels.cs

using UnityEngine;

public enum BlockColors {blank, red, blue, green, yellow, cyan, white, purple};

[System.Serializable] public class level {
	#if UNITY_EDITOR
	[HideInInspector] public bool showBoard;
	#endif
	public int rows = 9;
	public int column = 9;
	public BlockColors [,] board = new BlockColors [collumns, rows];
}


public class Levels : MonoBehaviour {

	public Level[] allLevels;

}

Editor/LevelEditor.cs

using UnityEngine;
using UnityEditor;


[CustomEditor(typeof(Levels))]
public class LevelEditor : Editor {

	public bool showLevels = true;

	public override void OnInspectorGUI() {
		Levels levels = (Levels)target;
		EditorGUILayout.Space ();

		showLevels = EditorGUILayout.Foldout (showLevels, "Levels ("+levels.allLevels.Length+")");
		if (showLevels) {
			EditorGUI.indentLevel++;
			for (ushort i = 0; i < levels.allLevels.Length; i++) {
				
				levels.allLevels_.showBoard = EditorGUILayout.Foldout(levels.allLevels*.showBoard, "Board");*_

_ if (levels.allLevels .showBoard) {_

* EditorGUI.indentLevel = 0;*

* GUIStyle tableStyle = new GUIStyle (“box”);*
* tableStyle.padding = new RectOffset (10, 10, 10, 10);*
* tableStyle.margin.left = 32;*

* GUIStyle headerColumnStyle = new GUIStyle ();*
* headerColumnStyle.fixedWidth = 35;*

* GUIStyle columnStyle = new GUIStyle ();*
* columnStyle.fixedWidth = 65;*

* GUIStyle rowStyle = new GUIStyle ();*
* rowStyle.fixedHeight = 25;*

* GUIStyle rowHeaderStyle = new GUIStyle ();*
* rowHeaderStyle.fixedWidth = columnStyle.fixedWidth - 1;*

* GUIStyle columnHeaderStyle = new GUIStyle ();*
* columnHeaderStyle.fixedWidth = 30;*
* columnHeaderStyle.fixedHeight = 25.5f;*

* GUIStyle columnLabelStyle = new GUIStyle ();*
* columnLabelStyle.fixedWidth = rowHeaderStyle.fixedWidth - 6;*
* columnLabelStyle.alignment = TextAnchor.MiddleCenter;*
* columnLabelStyle.fontStyle = FontStyle.Bold;*

* GUIStyle cornerLabelStyle = new GUIStyle ();*
* cornerLabelStyle.fixedWidth = 42;*
* cornerLabelStyle.alignment = TextAnchor.MiddleRight;*
* cornerLabelStyle.fontStyle = FontStyle.BoldAndItalic;*
* cornerLabelStyle.fontSize = 14;*
* cornerLabelStyle.padding.top = -5;*

* GUIStyle rowLabelStyle = new GUIStyle ();*
* rowLabelStyle.fixedWidth = 25;*
* rowLabelStyle.alignment = TextAnchor.MiddleRight;*
* rowLabelStyle.fontStyle = FontStyle.Bold;*

* GUIStyle enumStyle = new GUIStyle (“popup”);*
* rowStyle.fixedWidth = 65;*

* EditorGUILayout.BeginHorizontal (tableStyle);*
_ for (int x = -1; x < levels.allLevels .collumns; x++) {
* EditorGUILayout.BeginVertical ((x == -1) ? headerColumnStyle : columnStyle);
for (int y = -1; y < levels.allLevels .rows; y++) {
if (x == -1 && y == -1) {
EditorGUILayout.BeginVertical (rowHeaderStyle);
EditorGUILayout.LabelField (“[X,Y]”, cornerLabelStyle);
EditorGUILayout.EndHorizontal ();
} else if (x == -1) {
EditorGUILayout.BeginVertical (columnHeaderStyle);
EditorGUILayout.LabelField (y.ToString (), rowLabelStyle);
EditorGUILayout.EndHorizontal ();
} else if (y == -1) {
EditorGUILayout.BeginVertical (rowHeaderStyle);
EditorGUILayout.LabelField (x.ToString (), columnLabelStyle);
EditorGUILayout.EndHorizontal ();
}*_

* if (x >= 0 && y >= 0) {*
* EditorGUILayout.BeginHorizontal (rowStyle);*
levels.allLevels .board [x, y] = (BlockColors)EditorGUILayout.EnumPopup (levels.allLevels .board [x, y], enumStyle);
* EditorGUILayout.EndHorizontal ();*
* }*
* }*
* EditorGUILayout.EndVertical ();*
* }*
* EditorGUILayout.EndHorizontal ();*

* }*

* }*
* }*
* }*
}

Hi, You could use an array of 1 dimension.

To set or get data in the array you must use the following

//Create the 1-dimensional array that will represent the 2d array
public BlockColors [] board = new BlockColors [collumns * rows];

//Translate the index [x, y] to the index in the 1D array
//Where x and y represent indexes, and width, the width of the matrix
board[x + y * width]

I hope it helps you

Unity couldn’t by default serialize 2 dimensional arrays. What you have to do is to create your own serializable data structure that represents a 2D array and show it on inspector like you did with your custom editor script. Also keep in mind that MonoBehaviours always reset on play unlike ScriptableObjects.

I’d recommend creating a serializable container class that has a 1-D array that is marked with [SerializeField] attribute and then create another serializable class that contains a one dimensional array of the type you just created and mark it with [SerializeField], so now you have a class that contains an array of a class that contains an array! this way unity knows how to serialize this data structure.

Then all you have to do is to create a class that inherits from ScriptableObject then add the data structure type you created and save that as an asset.

I hope this helped :slight_smile:

Have you considered making your changes INGAME and creating a save function? I didn’t even look at much of the code but that was just an idea. That looks like a mixer board to me and all I can think of is you trying to change and save the mixer on the back end. That would require merging your editor with unity. Creating a save file would allow you to set those when you hit play, then hit save, and they will bounce back when you hit play no problem.