unity开发之地图分割(一)

游戏中经常会遇到地图分区域块的需求,并且要根据策划的配置来实现,简单说下我的实现方法,首先对需要分块的地形生成可编辑顶点,请参考这位大大写的插件http://blog.csdn.net/qq992817263/article/details/51579913
然后根据生成出来的顶点,进行连接生成区域块(PS: 请保证顺时针编辑节点),下图是我连接顶点形成的区域块:

unity开发之地图分割(一)_第1张图片
image.png

1.定义区域块结构

struct Block
{
    public List linePosList;
}

2.通过当前编辑的节点生成区域块

image.png

lineVertices:存储当前编辑的区域块顶点
blockList:存储已编辑完成的区域块

private void CreateBlock()
    {
        if (lineVertices.Count > 3)
        {
            Vector3 start = lineVertices[0].transform.position;
            Vector3 end = lineVertices[lineVertices.Count - 1].transform.position;

            if (!(Mathf.FloorToInt(start.x * 1000) == Mathf.FloorToInt(end.x * 1000) && Mathf.FloorToInt(start.y * 1000) == Mathf.FloorToInt(end.y * 1000) && Mathf.FloorToInt(start.z * 1000) == Mathf.FloorToInt(end.z * 1000)))
            {
                EditorUtility.DisplayDialog("提示", "该区域块不是封闭的!", "确定");
                return;
            }
            
            bool[] IsObtuse = new bool[lineVertices.Count - 1];
            for (int i = 0; i < lineVertices.Count - 1; ++i)
            {
                Vector3 a = lineVertices[(i + lineVertices.Count - 2) % (lineVertices.Count - 1)].transform.position - lineVertices[i].transform.position;
                Vector3 b = lineVertices[(i + 1) % (lineVertices.Count - 1)].transform.position - lineVertices[i].transform.position;
                if (Vector3.Cross(a.normalized, b.normalized).y > 0)
                {
                    IsObtuse[i] = true;
                }
                else
                {
                    IsObtuse[i] = false;
                }
            }
            for (int i = 0; i < IsObtuse.Length; ++i)
            {
                if (IsObtuse[i] && IsObtuse[(i + 1) % IsObtuse.Length])
                {
                    EditorUtility.DisplayDialog("提示", "区域块中存在相邻的凹点, 请重新编辑!", "确定");
                }
            }

            GameObject line = new GameObject();
            LineRenderer _lineRenderer = line.AddComponent();
            _lineRenderer.material = new Material(ShaderPool.TrySpawn("Particles/Additive"));
            _lineRenderer.SetColors(lineColor, lineColor);
            _lineRenderer.SetWidth(lineSize, lineSize);
            _lineRenderer.useWorldSpace = true;
            _lineRenderer.SetVertexCount(lineVertices.Count);

            Block newBlock = new Block();
            if (newBlock.linePosList == null)
            {
                newBlock.linePosList = new List();
            }

            for (int i = 0; i < lineVertices.Count; ++i)
            {
                Vector3 position = new Vector3((float)Math.Round(lineVertices[i].transform.position.x, 2), (float)Math.Round(lineVertices[i].transform.position.y, 2), (float)Math.Round(lineVertices[i].transform.position.z, 2));
                _lineRenderer.SetPosition(i, position);
                newBlock.linePosList.Add(position);
            }
            blockList.Add(newBlock);

            line.name = "CreateBlock_" + BlockCnt;
            ++BlockCnt;
            lineList.Add(line);

            lineVertices.Clear();
            _serializedObject.Update();
        }
        else
        {
            EditorUtility.DisplayDialog("提示", "顶点数少于4,无法生成封闭的区域块!", "确定");
        }
    }

3.导出编辑完成的区域块数据

outputPath:导出数据存储路径

private void ExportToFile()
    {
        if (!Directory.Exists(outputPath))
        {
            Directory.CreateDirectory(outputPath);
        }

        using (FileStream stream = File.Open(outputPath + map.name + ".txt", FileMode.OpenOrCreate, FileAccess.Write))
        {
            stream.SetLength(0);

            byte[] bys = System.Text.Encoding.UTF8.GetBytes(GenInfos());
            stream.Write(bys, 0, bys.Length);
            stream.Close();
        }
    }
private string GenInfos()
    {
        StringBuilder sb = new StringBuilder(2048);
        for (int i = 0; i < blockList.Count; ++i)
        {
            sb.AppendLine(blockList[i].linePosList.Count.ToString());
            for (int j = 0; j < blockList[i].linePosList.Count; ++j)
            {
                sb.AppendLine(blockList[i].linePosList[j].x + "," + blockList[i].linePosList[j].y + "," + blockList[i].linePosList[j].z);
            }
        }
        return sb.ToString();
    }

到此我们已经将策划编辑的分区数据存储完成,下篇将进行数据读取,并还原编辑的区域块,具体问题见下篇。

你可能感兴趣的:(unity开发之地图分割(一))