我正在尝试为Unity中的某个类创建自定义检查器:
我的主要课程如下:
public class MapGenerator : MonoBehaviour
{
public int width;
public int height;
[SerializeField]
public List<Tile> tiles;
}
我的Tile类看起来像这样:
[System.Serializable]
public class Tile {
public TileType tileType;
public Sprite tileTexture;
}
这是我的编辑班:
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();
}
我的问题是,如果我更改了Tiles List的任何属性,这意味着如果我修改枚举或将纹理添加到其中一个变量,则在更改场景或Unity关闭后,将删除分配的值或纹理。
这是我第一次在编辑器中尝试这样的东西。任何帮助表示赞赏。
答案 0 :(得分:1)
在我看来,问题是Unity没有认识到场景的变化所以我强迫他们使用
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
我发现点击“重置组件”然后单击我的按钮“添加新平铺”后的行为,新的平铺添加成功然后我尝试更改场景并统一要求保存场景,我点击“好的“当我回到现场时一切都很好,所以我尝试添加一个新的瓷砖,添加了新的瓷砖但是当我改变了场景时Unity没有要求保存更改。
现在我的MapGeneratorEditor.cs脚本如下所示:
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());
}
}