using UnityEngine;
|
using System.Collections.Generic;
|
using UnityEditor;
|
using System.IO;
|
using UnityEngine.AI;
|
using System;
|
|
public class NavMeshExport : EditorWindow
|
{
|
static byte[] _writedBytes = null;
|
/** 字节写入位置索引 */
|
static int _writeIndex = 128;
|
|
private static int[][] m_Datas;
|
// 主文件
|
private static List<List<int>> m_MainData = null;
|
|
[MenuItem("美术工具/场景/合并布怪区")]
|
static void Init()
|
{
|
var _window = CreateInstance<NavMeshExport>();
|
_window.Show();
|
}
|
|
private void BuildCurData()
|
{
|
float _navWidth;
|
float _navHeight;
|
float _maxWidth;
|
float _maxHeight;
|
|
Vector3[] _navVertices = NavMesh.CalculateTriangulation().vertices;
|
if (_navVertices == null || _navVertices.Length <= 0)
|
{
|
return;
|
}
|
|
List<Vector3> _chkList = new List<Vector3>(_navVertices);
|
_chkList.Sort((Vector3 v1, Vector3 v2) =>
|
{
|
return v1.x > v2.x ? -1 : 1;
|
});
|
|
_navWidth = _chkList[0].x - _chkList[_chkList.Count - 1].x;
|
_maxWidth = _navWidth + _chkList[_chkList.Count - 1].x;
|
|
_chkList.Sort((Vector3 v1, Vector3 v2) =>
|
{
|
return v1.z > v2.z ? -1 : 1;
|
});
|
|
_navHeight = _chkList[0].z - _chkList[_chkList.Count - 1].z;
|
_maxHeight = _navHeight + _chkList[_chkList.Count - 1].z;
|
|
float _outWidth = (int)(_maxWidth * 2) + 1;
|
float _outHeight = (int)(_maxHeight * 2) + 1;
|
|
float _column;
|
float _row;
|
|
var _curData = new List<List<int>>();
|
|
for (int r = 0; r < _outHeight; ++r)
|
{
|
List<int> _rowData = new List<int>();
|
for (int c = 0; c < _outWidth; ++c)
|
{
|
_column = c * .5f;
|
_row = r * .5f;
|
|
if (IsInNavmeshArea(_column, _row))
|
{
|
_rowData.Add(00);
|
}
|
else
|
{
|
_rowData.Add(03);
|
}
|
}
|
_curData.Add(_rowData);
|
}
|
|
MapCollide _file = new MapCollide();
|
_file.width = _curData[0].Count;
|
_file.height = _curData.Count;
|
|
_file.data = new int[_curData.Count][];
|
for (int r = 0; r < _curData.Count; ++r)
|
{
|
_file.data[r] = new int[_curData[r].Count];
|
for (int c = 0; c < _curData[r].Count; ++c)
|
{
|
_file.data[r][c] = _curData[r][c];
|
}
|
}
|
|
LitJson.JsonData _jsonData = LitJson.JsonMapper.ToJson(_file);
|
|
string _dirPath = Application.dataPath + "/Editor/MapCollideFiles/";
|
|
if (!Directory.Exists(_dirPath))
|
{
|
Directory.CreateDirectory(_dirPath);
|
}
|
|
string _filePath = _dirPath + UnityEngine.SceneManagement.SceneManager.GetActiveScene().name + ".json";
|
|
using (StreamWriter _sw = new StreamWriter(_filePath))
|
{
|
_sw.Write(_jsonData.ToString());
|
}
|
|
AssetDatabase.Refresh();
|
}
|
|
private void CombineFromFile()
|
{
|
string _inputPath = EditorUtility.OpenFilePanel("打开合并文件",
|
Application.dataPath + "/Editor/MapCollideFiles/", "asset");
|
|
if (string.IsNullOrEmpty(_inputPath))
|
{
|
return;
|
}
|
|
string _fileName = Path.GetFileNameWithoutExtension(_inputPath);
|
|
string _configPath = "Assets/Editor/MapCollideFiles/" + _fileName + ".asset";
|
MapCombine _config = AssetDatabase.LoadAssetAtPath<MapCombine>(_configPath);
|
|
if (_config == null)
|
{
|
Debug.LogErrorFormat("{0} 文件无法读取.", _configPath);
|
return;
|
}
|
|
string _mainFilePath = Application.dataPath + "/Editor/MapCollideFiles/" + _config.mainFileName + ".json";
|
string _jsonData = string.Empty;
|
|
using (StreamReader _sr = new StreamReader(_mainFilePath))
|
{
|
_jsonData = _sr.ReadToEnd();
|
}
|
|
if (string.IsNullOrEmpty(_jsonData))
|
{
|
Debug.LogErrorFormat("{0} 文件无法读取.", _config.mainFileName);
|
return;
|
}
|
|
MapCollide _file = LitJson.JsonMapper.ToObject<MapCollide>(_jsonData);
|
|
if (m_MainData == null)
|
{
|
m_MainData = new List<List<int>>();
|
}
|
else
|
{
|
m_MainData.Clear();
|
}
|
|
for (int i = 0; i < _file.height; ++i)
|
{
|
List<int> _row = new List<int>();
|
for (int j = 0; j < _file.width; ++j)
|
{
|
_row.Add(_file.data[i][j]);
|
}
|
m_MainData.Add(_row);
|
}
|
|
for (int i = 0; i < _config.dataList.Count; ++i)
|
{
|
Combine(_config.dataList[i]);
|
}
|
|
_writedBytes = null;
|
|
string _exportPath = EditorUtility.SaveFilePanel("",
|
"",
|
_config.mainFileName,
|
"col");
|
|
if (string.IsNullOrEmpty(_exportPath))
|
{
|
return;
|
}
|
|
if (File.Exists(_exportPath))
|
{
|
File.Delete(_exportPath);
|
}
|
|
WriteBytes(BitConverter.GetBytes((uint)(m_MainData[0].Count)));
|
WriteBytes(BitConverter.GetBytes((uint)(m_MainData.Count)));
|
|
m_Datas = new int[m_MainData.Count][];
|
for (int i = 0; i < m_Datas.Length; ++i)
|
{
|
m_Datas[i] = new int[m_MainData[i].Count];
|
}
|
|
for (int r = 0; r < m_MainData.Count; ++r)
|
{
|
for (int c = 0; c < m_MainData[r].Count; ++c)
|
{
|
m_Datas[r][c] = m_MainData[r][c];
|
}
|
}
|
|
for (int i = 0; i < m_Datas.Length; i++)
|
{
|
WriteBytes(m_Datas[i]);
|
}
|
|
WriteToFile(_exportPath);
|
}
|
|
private Vector3 m_ChkPos;
|
|
private void OnGUI()
|
{
|
if (GUILayout.Button("合并配置文件地图"))
|
{
|
CombineFromFile();
|
}
|
|
if (GUILayout.Button("生成当前地图的合并文件"))
|
{
|
BuildCurData();
|
}
|
|
GUILayout.Space(10);
|
EditorGUILayout.BeginHorizontal();
|
m_ChkPos = EditorGUILayout.Vector3Field("测试点", m_ChkPos);
|
if (GUILayout.Button("测试"))
|
{
|
if (IsInNavmeshArea(m_ChkPos.x, m_ChkPos.z))
|
{
|
Debug.Log("正常点...........");
|
}
|
else
|
{
|
Debug.Log("障碍点...........");
|
}
|
}
|
EditorGUILayout.EndHorizontal();
|
|
if (GUILayout.Button("直接导出当前地图.col文件"))
|
{
|
Export();
|
}
|
|
if (m_Datas == null)
|
{
|
return;
|
}
|
|
Rect _rect = new Rect(0, 0, 2, 2);
|
|
for (int i = 0; i < m_Datas.Length; ++i)
|
{
|
if (m_Datas[i] == null)
|
{
|
continue;
|
}
|
|
for (int j = 0; j < m_Datas[i].Length; ++j)
|
{
|
if (m_Datas[i][j] == 00)
|
{
|
GUI.color = Color.green;
|
}
|
else if (m_Datas[i][j] == 03)
|
{
|
GUI.color = Color.red;
|
}
|
|
_rect.position = new Vector2(j * 2 + 4, i * 2 + 72);
|
|
GUI.Box(_rect, "");
|
}
|
}
|
}
|
|
private void OnDisable()
|
{
|
m_Datas = null;
|
m_MainData = null;
|
}
|
|
private void Combine(MapCombine.MapCombineInfo info)
|
{
|
if (m_MainData == null)
|
{
|
return;
|
}
|
|
// 读取文件
|
string _filePath = Application.dataPath + "/Editor/MapCollideFiles/" + info.fileName + ".json";
|
string _jsonData = string.Empty;
|
|
using (StreamReader _sr = new StreamReader(_filePath))
|
{
|
_jsonData = _sr.ReadToEnd();
|
}
|
|
if (string.IsNullOrEmpty(_jsonData))
|
{
|
Debug.LogErrorFormat("{0} 文件无法读取.", info.fileName);
|
return;
|
}
|
|
MapCollide _file = LitJson.JsonMapper.ToObject<MapCollide>(_jsonData);
|
|
int _prevRowCount = m_MainData.Count;
|
int _prevColumnCount = m_MainData[0].Count;
|
|
int _curRowCount = _file.height;
|
int _curColumnCount = _file.width;
|
|
int _newRowCount = 0;
|
int _newColumnCount = 0;
|
|
// 填入的偏移R + 新地图的高度 与 之前地图的高度进行对比, 得到差值
|
int _deltaRowCount = info.offsetY + _curRowCount - _prevRowCount;
|
|
// 差值大于0, 则新建一个数组, 此数组为旧的R + 差值
|
if (_deltaRowCount > 0)
|
{
|
_newRowCount = _prevRowCount + _deltaRowCount;
|
}
|
else
|
{
|
_newRowCount = _prevRowCount;
|
}
|
|
// 列同理
|
int _deltaColumnCount = info.offsetX + _curColumnCount - _prevColumnCount;
|
|
if (_deltaColumnCount > 0)
|
{
|
_newColumnCount = _prevColumnCount + _deltaColumnCount;
|
}
|
else
|
{
|
_newColumnCount = _prevColumnCount;
|
}
|
|
// 扩容
|
for (int i = m_MainData.Count; i < _newRowCount; ++i)
|
{
|
List<int> _tmp = new List<int>();
|
for (int j = 0; j < _prevColumnCount; ++j)
|
{
|
_tmp.Add(03);
|
}
|
m_MainData.Add(_tmp);
|
}
|
|
for (int i = 0; i < m_MainData.Count; ++i)
|
{
|
for (int j = _prevColumnCount; j < _newColumnCount; ++j)
|
{
|
m_MainData[i].Add(03);
|
}
|
}
|
|
// 赋值
|
for (int i = 0; i < _file.data.Length; ++i)
|
{
|
for (int j = 0; j < _file.data[i].Length; ++j)
|
{
|
m_MainData[i + info.offsetY][j + info.offsetX] = _file.data[i][j];
|
}
|
}
|
}
|
|
static void Export()
|
{
|
string path = EditorUtility.SaveFilePanel("",
|
"",
|
UnityEngine.SceneManagement.SceneManager.GetActiveScene().name,
|
"col");
|
|
if (string.IsNullOrEmpty(path))
|
{
|
return;
|
}
|
|
if (File.Exists(path))
|
{
|
File.Delete(path);
|
}
|
|
float _navWidth;
|
float _navHeight;
|
float _maxWidth;
|
float _maxHeight;
|
|
Vector3[] _navVertices = NavMesh.CalculateTriangulation().vertices;
|
if (_navVertices == null || _navVertices.Length <= 0)
|
{
|
return;
|
}
|
|
List<Vector3> _chkList = new List<Vector3>(_navVertices);
|
_chkList.Sort((Vector3 v1, Vector3 v2) =>
|
{
|
return v1.x > v2.x ? -1 : 1;
|
});
|
|
_navWidth = _chkList[0].x - _chkList[_chkList.Count - 1].x;
|
_maxWidth = _navWidth + _chkList[_chkList.Count - 1].x;
|
|
_chkList.Sort((Vector3 v1, Vector3 v2) =>
|
{
|
return v1.z > v2.z ? -1 : 1;
|
});
|
|
_navHeight = _chkList[0].z - _chkList[_chkList.Count - 1].z;
|
_maxHeight = _navHeight + _chkList[_chkList.Count - 1].z;
|
|
int _outWidth = (int)(_maxWidth * 2) + 1;
|
int _outHeight = (int)(_maxHeight * 2) + 1;
|
|
WriteBytes(BitConverter.GetBytes((uint)(_outWidth)));
|
WriteBytes(BitConverter.GetBytes((uint)(_outHeight)));
|
|
Debug.LogFormat("地图宽度: {0}, 地图高度: {1}", _outWidth, _outHeight);
|
|
float _column;
|
float _row;
|
|
int[][] _datas = new int[_outHeight][];
|
for (int i = 0; i < _datas.Length; i++)
|
{
|
_datas[i] = new int[_outWidth];
|
}
|
|
//System.Text.StringBuilder _sb1 = new System.Text.StringBuilder();
|
|
for (int r = 0; r < _outHeight; ++r)
|
{
|
for (int c = 0; c < _outWidth; ++c)
|
{
|
_column = c * .5f;
|
_row = r * .5f;
|
|
if (IsInNavmeshArea(_column, _row))
|
{
|
_datas[r][c] = 00;
|
//_sb1.Append("0");
|
}
|
else
|
{
|
_datas[r][c] = 03;
|
//_sb1.Append("#");
|
}
|
|
}
|
//_sb1.Append("\r\n");
|
}
|
|
//using (StreamWriter _writer = new StreamWriter(Application.dataPath + "/aaa.txt"))
|
//{
|
// _writer.Write(_sb1.ToString());
|
//}
|
|
for (int i = 0; i < _datas.Length; i++)
|
{
|
WriteBytes(_datas[i]);
|
}
|
|
WriteToFile(path);
|
}
|
|
private static bool IsInNavmeshArea(float column, float row)
|
{
|
int _mask = 1 << LayerMask.NameToLayer("Navmesh");
|
return Physics.Raycast(new Vector3(column, 100, row), Vector3.down, 200, _mask)
|
|| Physics.Raycast(new Vector3(column + .5f, 100, row), Vector3.down, 200, _mask)
|
|| Physics.Raycast(new Vector3(column, 100, row + .5f), Vector3.down, 200, _mask)
|
|| Physics.Raycast(new Vector3(column + .5f, 100, row + .5f), Vector3.down, 200, _mask);
|
}
|
|
|
private static void WriteToFile(string path)
|
{
|
FileStream fs = File.Open(path, FileMode.CreateNew, FileAccess.ReadWrite);
|
BinaryWriter bw = new BinaryWriter(fs);
|
//将byte数组写入文件中
|
bw.Write(_writedBytes, 0, _writedBytes.Length);
|
bw.Flush();
|
bw.Close();
|
fs.Dispose();
|
fs.Close();
|
_writeIndex = 128;
|
_writedBytes = null;
|
}
|
|
/// <summary>
|
/// 写入一段字节数据
|
/// </summary>
|
/// <param name="vBytes"></param>
|
private static void WriteBytes(byte[] vBytes)
|
{
|
Array.Resize(ref _writedBytes, _writeIndex + vBytes.Length);
|
vBytes.CopyTo(_writedBytes, _writeIndex);
|
_writeIndex = _writedBytes.Length;
|
}
|
|
/// <summary>
|
/// 转整型数值数组为字节
|
/// </summary>
|
/// <param name="vInts"></param>
|
/// <param name="vType"></param>
|
private static void WriteBytes(int[] vInts)
|
{
|
int l = vInts.Length;
|
byte[] vRst;
|
int i;
|
vRst = new byte[l];
|
for (i = 0; i < l; i++)
|
{
|
Array.Copy(BitConverter.GetBytes((byte)vInts[i]), 0, vRst, i, 1);
|
}
|
WriteBytes(vRst);
|
}
|
}
|