首页 > 解决方案 > 自动填充检查器数组

问题描述

我有一个二维数组(基于网格)并想通过检查器填充它。给你一个关于游戏的想法

在此处输入图像描述

所以我的地面脚本包含所有这些单元格。

public class Ground : MonoBehaviour
{
    public Cell[,] cells;

    private void Start()
    {
        Debug.Log(cells);
    }
}

由于管理所有这些单元并将它们分配给我考虑自动化它的地面脚本将是很多工作。所以每当我添加一个游戏对象(作为一个孩子)并将单元组件分配给它时,地面应该自动将此单元添加到数组中。为了实现这一点,我考虑为检查员创建一个编辑器脚本。

[CustomEditor(typeof(Ground))]
public class GroundEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Ground ground = (Ground)target;

        Dictionary<Vector2Int, Cell> cells = new Dictionary<Vector2Int, Cell>();
        int maximumHorizontalLength = 0;
        int maximumVerticalLength = 0;

        foreach (Transform groundCell in ground.transform)
        {
            Cell cell = groundCell.GetComponent<Cell>();

            if (cell != null)
            {
                Vector3 cellPosition = groundCell.position;
                Vector2Int cellIndices = new Vector2Int(Mathf.RoundToInt(cellPosition.x), Mathf.RoundToInt(cellPosition.z));
                cells.Add(cellIndices, cell);

                if (cellIndices.x > maximumHorizontalLength)
                {
                    maximumHorizontalLength = cellIndices.x;
                }

                if (cellIndices.y > maximumVerticalLength)
                {
                    maximumVerticalLength = cellIndices.y;
                }
            }
        }

        maximumHorizontalLength++;
        maximumVerticalLength++;

        ground.cells = new Cell[maximumHorizontalLength, maximumVerticalLength];

        for (int x = 0; x < maximumHorizontalLength; x++)
        {
            for (int y = 0; y < maximumVerticalLength; y++)
            {
                ground.cells[x, y] = cells[new Vector2Int(x, y)];
            }
        }
    }
}

所以我想在开始游戏之前创建这个二维网格以节省资源。我不想在玩的时候按标签或类型搜索。而且我认为这种方法可以节省时间。

不幸的是,在开始游戏时,Debug.Log 打印为 null。我希望用这条线填充它ground.cells = new Cell[maximumHorizontalLength, maximumVerticalLength];我错过了什么吗?这甚至可能吗?

标签: c#unity3d

解决方案


Unity 序列化程序不支持多维数组,因此您需要重新构建您希望如何在每个 Cell 上存储数据。一种选择是创建一个从 MonoBehaviour 派生的新自定义类来存储此数据并将其放置在场景中的某个位置:

[System.Serializable]
public class CellData : MonoBehaviour
{
    [System.Serializable]
    public class CellReference
    {
        public int xPos;
        public int yPos;
        public Cell cell;

        public CellReference(Vector2Int posVal, Cell celVal)
        {
            xPos = posVal.x; yPos = posVal.y; cell = celVal;
        }
    }

    public List<CellReference> cellReferences = new List<CellReference>();
}

然后可以通过检查器通过对 Ground 和 GroundEditor 类的以下更改来填充它:

public class Ground : MonoBehaviour
{
    public CellData cells;

    private void Start()
    {
        Debug.Log(cells);
    }
}

[CustomEditor(typeof(Ground))]
public class GroundEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if (GUILayout.Button("Refresh Cell References"))
        {
            Ground ground = (Ground)target;

            ground.cells.cellReferences = new List<CellData.CellReference>();

            foreach (Transform groundCell in ground.transform)
            {
                Cell cell = groundCell.GetComponent<Cell>();

                if (cell != null)
                {
                    Vector3 cellPosition = groundCell.position;
                    Vector2Int cellIndices = new Vector2Int(Mathf.RoundToInt(cellPosition.x), Mathf.RoundToInt(cellPosition.z));

                    ground.cells.cellReferences.Add(new CellData.CellReference(cellIndices, cell));
                }
            }
        }
    }
}

将 CellsData 脚本连接到您放置的 Ground 脚本,每次在检查器中按下“刷新单元格引用”按钮时,这将生成一个新的单元格列表。


推荐阅读