如何保存二维数组,作为变量检查器的一部分?

时间:2015-10-26 02:17:07

标签: c# unity3d unity3d-editor

我有一个包含一些变量的Component。重新启动Unity时将保存变量。 (int,color,float)

using UnityEngine;
using System.Collections;

public class Grid : MonoBehaviour
{
    public float startX = 0;
    public float startZ = 0;

    public int width = 1000;
    public int height = 1000;

    public float boxWidth = 32.0f;
    public float boxHeight = 32.0f;

    public float px;
    public float pz;

    public Color color = Color.white;
    public bool[,] map;

    void OnDrawGizmos()
    {
        if (map != null)
        {
            Vector3 pos = transform.position;

            px = pos.x + startX;
            pz = pos.z + startZ;

            Gizmos.color = color;

            Vector3 size = new Vector3(boxWidth, 0f, boxHeight);

            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < height; z++)
                {
                    if (map[x, z])
                    {
                        Gizmos.DrawCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
                    }
                    else
                    {
                        Gizmos.DrawWireCube(new Vector3(px + x * boxWidth, pos.y + 1, pz + z * boxHeight), size);
                    }
                }
            }
        }
    }
}

要编辑我有检查员的变量:

using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomEditor (typeof(Grid))]
public class GridEditor : Editor
{
    Grid grid;

    public void OnEnable()
    {
        grid = (Grid)target;
        SceneView.onSceneGUIDelegate += GridUpdate;

        if (grid.map == null)
        {
            grid.map = new bool[grid.width, grid.height];
            for (int x = 0; x < grid.width; x++)
            {
                for (int y = 0; y < grid.height; y++)
                {
                    grid.map[x, y] = false;
                }
            }
        }
    }

    public void OnDisable()
    {
        SceneView.onSceneGUIDelegate -= GridUpdate;
    }

    private int lastX = -1;
    private int lastZ = -1;
    void OnSceneGUI()
    {
        Event e = Event.current;
        Camera camera = Camera.current;

        Vector3 mousePos =  Vector3.zero; // = camera.ScreenToWorldPoint(new Vector3(e.mousePosition.x, e.mousePosition.y, distance));

        if (EventType.KeyDown == e.type && KeyCode.LeftControl == e.keyCode)
        {

            Ray ray = camera.ScreenPointToRay(new Vector3(e.mousePosition.x, -e.mousePosition.y + camera.pixelHeight, 0));
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 2550f))
            {
                mousePos = hit.point;
            }

            int x = Mathf.RoundToInt((mousePos.x - grid.px)/grid.boxWidth);
            int z = Mathf.RoundToInt((mousePos.z - grid.pz)/grid.boxHeight);

            if (x >= 0 && x < grid.width && z >= 0 && z < grid.height)
            {
                if (x != lastX || z != lastZ)
                {
                    grid.map[x, z] = !grid.map[x, z];
                    lastX = x;
                    lastZ = z;
                    SceneView.RepaintAll();
                }
            }
        }
    }

    public override void OnInspectorGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label(" Start x ");
        grid.startX = EditorGUILayout.FloatField(grid.startX, GUILayout.Width(50));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label(" Start z ");
        grid.startZ = EditorGUILayout.FloatField(grid.startZ, GUILayout.Width(50));
        GUILayout.EndHorizontal();


        GUILayout.BeginHorizontal();
        GUILayout.Label(" Grid Width ");
        grid.width = EditorGUILayout.IntField(grid.width, GUILayout.Width(50));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label(" Grid Height ");
        grid.height = EditorGUILayout.IntField(grid.height, GUILayout.Width(50));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label(" Box Width ");
        grid.boxWidth = EditorGUILayout.FloatField(grid.boxWidth, GUILayout.Width(50));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label(" Box Height ");
        grid.boxHeight = EditorGUILayout.FloatField(grid.boxHeight, GUILayout.Width(50));
        GUILayout.EndHorizontal();

        if (GUILayout.Button("Open Grid Window", GUILayout.Width(255)))
        {   
           GridWindow window = (GridWindow) EditorWindow.GetWindow(typeof (GridWindow));
           window.Init();
        }

        SceneView.RepaintAll();
    }
}

不幸的是,我无法弄清楚如何存储boolean的二维数组(map [,]),所以他在重启Unity时仍然存在。所有我来到它来进行文件序列化并在启动App中查找文件。 (阵列可以是一个很大的1000x20)也许你可以建议一个更好的主意?谢谢!请原谅我的英语。

1 个答案:

答案 0 :(得分:1)

问题实际上与数据类型无关,例如地图,在您的情况下。您可以尝试ScriptableObject类,它不需要附加到某些游戏对象

从ScriptableObject派生一个类,并将[Serializable]属性添加到类

[Serializable]
class MyData: ScriptableObject
{
     public bool[,] map;
     void OnEnable() { 
         //... do something to initialise the map or reload the map
     }
}

实例化用于保存数据的对象

//in this case MyData contains your map data
var data = SciptableObject.CreateInstance(typeof(MyData));

将其保存到Unity数据库:

AssetDatabase.CreateAsset(data,  "Assets/SomeFolder/abc.asset");
AssetDatabase.SaveAssets()
AssetDatabase.Refresh();

检查某些资产是否已存在于资产中:

var data = AssetDatabase.LoadAssetAtPath("Assets/SomeFolder/abc.asset",
    typeof(SomeData));
if(data != null) {
   //Your own logic to consume the map or whatever data
}

这样,Unity重新启动时将保存所有变量,您可以在类上添加[InitializeOnLoad]属性以使其自动加载。并且您可以在统一内部看到abc.asset文件,并使用您的自定义编辑器编辑地图也是小菜一碟。

相关问题