1

我正在尝试为我在 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 关闭,分配的值或纹理将被删除。

这是我第一次在编辑器中尝试这样的事情。任何帮助表示赞赏。

4

1 回答 1

1

在我看来,问题在于 Unity 没有识别现场的变化,所以我强迫他们使用

EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());

我在点击“重置组件”然后点击我的按钮“添加新瓷砖”后发现了这种行为,新瓷砖添加成功然后我尝试更改场景并且统一要求保存场景,我点击“确定”并当我回到场景时一切都很好,所以我尝试添加一个新的 Tile,新的 Tile 被添加但是当我改变场景时 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());


    }


}
于 2017-07-05T08:02:59.167 回答