游戏中经常会遇到地图分区域块的需求,并且要根据策划的配置来实现,简单说下我的实现方法,首先对需要分块的地形生成可编辑顶点,请参考这位大大写的插件http://blog.csdn.net/qq992817263/article/details/51579913
然后根据生成出来的顶点,进行连接生成区域块(PS: 请保证顺时针编辑节点),下图是我连接顶点形成的区域块:
image.png
1.定义区域块结构
struct Block
{
public List<Vector3> 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>();
_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<Vector3>();
}
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();
}
到此我们已经将策划编辑的分区数据存储完成,下篇将进行数据读取,并还原编辑的区域块,具体问题见下篇。