Reputation: 490
I'm trying to create a custom inspector for one of my classes in Unity:
my main class looks like this:
public class MapGenerator : MonoBehaviour
{
public int width;
public int height;
[SerializeField]
public List<Tile> tiles;
}
my Tile class looks like this:
[System.Serializable]
public class Tile {
public TileType tileType;
public Sprite tileTexture;
}
And this is my Editor class:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(MapGenerator))]
public class MapGeneratorEditor : Editor
{
static bool showMapProperties = true;
static bool showTiles = true;
private SerializedObject _target;
SerializedProperty _mTiles;
int _mTilesSize;
public override void OnInspectorGUI()
{
MapGenerator myTarget = (MapGenerator)target;
SerializedObject _mySerializedTarget = new SerializedObject(target);
_mySerializedTarget.Update();
_mySerializedTarget.ApplyModifiedProperties();
//SerializedProperty _mySerializedTileList = _mySerializedTarget.FindProperty("tiles");
showMapProperties = EditorGUILayout.Foldout(showMapProperties, new GUIContent("Map Properties", "Set different properties fot the map generation."));
if (showMapProperties)
{
myTarget.width = EditorGUILayout.IntSlider(new GUIContent("Width", "Specify the width of the map"), myTarget.width, 1, 100);
myTarget.height = EditorGUILayout.IntSlider(new GUIContent("Height", "Specify the height of the map"), myTarget.height, 1, 100);
}
showTiles = EditorGUILayout.Foldout(showTiles, new GUIContent("Tiles List", "Tiles that are used to generate the map"));
if (showTiles)
{
_mTilesSize = myTarget.tiles.Count;
for (int y = 0; y < _mTilesSize; y++)
{
myTarget.tiles[y].tileType = (TileType)EditorGUILayout.EnumPopup("Tile Type", myTarget.tiles[y].tileType);
myTarget.tiles[y].tileTexture = (Sprite)EditorGUILayout.ObjectField(new GUIContent("Walkable Tile", "Tile where the enemies can walk"), myTarget.tiles[y].tileTexture, typeof(Sprite), false, null);
GUILayout.Label("____________________________________________________________________________________________________________");
}
if (GUILayout.Button(new GUIContent("Add new Tile", "Click to add a new tile to the list")))
{
Tile newTile = new Tile();
newTile.tileType = (TileType)EditorGUILayout.EnumPopup("Tile Type", TileType.NONE);
//newTile.tileType = (TileType)EditorGUILayout.EnumPopup(new GUIContent("Tile Type", "Type of selected tile"), newTile.tileType,GUIStyle.none,null);
newTile.tileTexture = (Sprite)EditorGUILayout.ObjectField(new GUIContent("Tile Texture", "Tile Texture"), newTile.tileTexture, typeof(Sprite), false, null);
//tiles.Add(newTile);
myTarget.tiles.Add(newTile);
}
if (GUILayout.Button(new GUIContent("Remove Tile", "Click to remove the last tile in the list")))
{
//myTarget.Invoke("RemoveTile", 0.0f);
//if (tiles.Count > 0)
// tiles.RemoveAt(tiles.Count - 1);
if (myTarget.tiles.Count > 0)
myTarget.tiles.RemoveAt(myTarget.tiles.Count - 1);
}
if (GUILayout.Button(new GUIContent("Remove All Tile", "Click to remove all tiles in the list")))
{
myTarget.tiles.Clear();
}
}
if (GUI.changed)
{
Debug.Log("GUI Changed");
EditorUtility.SetDirty(target);
}
_mySerializedTarget.Update();
_mySerializedTarget.ApplyModifiedProperties();
}
It looks like this in my editor:
My problem is that if I change any property of the Tiles List, meaning if I modify a enum or add a texture to one of the variables the value or texture assigned is removed once I change the scene or if Unity is closed.
This is the very first time that I tried something like this in the editor. any help is appreciated.
Upvotes: 1
Views: 3728
Reputation: 490
It seems to me like the problem was that Unity was not recognizing the changes on the scene so I have forced them using
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
I found that behaviour after clicking on "Reset Component" then clicking on my button "Add new Tile" , the new tile is added successfully then I tried to change the scene and unity asked to save the scene, I clicked on "OK" and when I returned to the scene everything was fine, so I tried adding a new Tile, the new tile is added but when I changed the scene Unity didn't asked to save changes.
now my MapGeneratorEditor.cs script looks like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
[CustomEditor(typeof(MapGenerator))]
public class MapGeneratorEditor : Editor
{
static bool showMapProperties = true;
static bool showTiles = true;
private SerializedObject _target;
SerializedProperty _mTiles;
int _mTilesSize;
MapGenerator myTarget;
public override void OnInspectorGUI()
{
myTarget = (MapGenerator)target;
//SerializedProperty _mySerializedTileList = _mySerializedTarget.FindProperty("tiles");
showMapProperties = EditorGUILayout.Foldout(showMapProperties, new GUIContent("Map Properties", "Set different properties fot the map generation."));
if (showMapProperties)
{
myTarget.width = EditorGUILayout.IntSlider(new GUIContent("Width", "Specify the width of the map"), myTarget.width, 1, 100);
myTarget.height = EditorGUILayout.IntSlider(new GUIContent("Height", "Specify the height of the map"), myTarget.height, 1, 100);
}
showTiles = EditorGUILayout.Foldout(showTiles, new GUIContent("Tiles List", "Tiles that are used to generate the map"));
if (showTiles)
{
_mTilesSize = myTarget.tiles.Count;
for (int y = 0; y < _mTilesSize; y++)
{
myTarget.tiles[y].tileType = (TileType)EditorGUILayout.EnumPopup("Tile Type", myTarget.tiles[y].tileType);
myTarget.tiles[y].tileTexture = (Sprite)EditorGUILayout.ObjectField(new GUIContent("Tile Texture", "Tile Texture"), myTarget.tiles[y].tileTexture, typeof(Sprite), false, null);
GUILayout.Label("____________________________________________________________________________________________________________");
}
if (GUILayout.Button(new GUIContent("Add new Tile", "Click to add a new tile to the list")))
{
Tile newTile = new Tile();
newTile.tileType = (TileType)EditorGUILayout.EnumPopup("Tile Type", TileType.NONE);
//newTile.tileType = (TileType)EditorGUILayout.EnumPopup(new GUIContent("Tile Type", "Type of selected tile"), newTile.tileType,GUIStyle.none,null);
newTile.tileTexture = (Sprite)EditorGUILayout.ObjectField(new GUIContent("Tile Texture", "Tile Texture"), newTile.tileTexture, typeof(Sprite), false, null);
//tiles.Add(newTile);
myTarget.tiles.Add(newTile);
}
if (GUILayout.Button(new GUIContent("Remove Tile", "Click to remove the last tile in the list")))
{
//myTarget.Invoke("RemoveTile", 0.0f);
//if (tiles.Count > 0)
// tiles.RemoveAt(tiles.Count - 1);
if (myTarget.tiles.Count > 0)
myTarget.tiles.RemoveAt(myTarget.tiles.Count - 1);
}
if (GUILayout.Button(new GUIContent("Remove All Tiles", "Click to remove all tiles in the list")))
{
myTarget.tiles.Clear();
}
}
if(GUI.changed)
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}
}
Upvotes: 1