123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 |
- using System;
- using System.IO;
- using System.Collections.Generic;
- using System.Text;
- using ET;
- using UnityEditor;
- using UnityEditor.UI;
- using UnityEngine;
- using UnityEngine.AI;
- using UnityEngine.Networking;
- using UnityEngine.SceneManagement;
- namespace ETEditor
- {
- /// <summary>
- /// 从Unity的NavMesh组件里导出地图数据,供服务器来使用
- /// https://blog.csdn.net/huutu/article/details/52672505
- /// </summary>
- public class NavMeshExporter: Editor
- {
- public const byte VERSION = 1;
- private class Vert
- {
- public int id;
- public float x;
- public float y;
- public float z;
- public UnityEngine.Vector3 ToVector3()
- {
- return new UnityEngine.Vector3(x, y, z);
- }
- }
- private class Face
- {
- public int id;
- public int area;
- public float centerX;
- public float centerZ;
- public float normalX;
- public float normalZ;
- public double normalA;
- public double normalB;
- public double normalC;
- public double normalD;
- public uint sortValue;
- public List<Vert> verts = new List<Vert>();
- }
- private class Pair
- {
- public float centerX;
- public float centerZ;
- public float distance;
- public Face firstEdgeFace;
- public int firstEdgeIndex;
- public Face secondEdgeFace;
- public int secondEdgeIndex;
- }
- private static List<Vert> vertList = new List<Vert>();
- private static List<Face> faceList = new List<Face>();
- private static List<Pair> pairList = new List<Pair>();
- private static Dictionary<Vert, Face> vertFaceDict = new Dictionary<Vert, Face>();
- private static Dictionary<Vert, Dictionary<Vert, Pair>> vertPairDict = new Dictionary<Vert, Dictionary<Vert, Pair>>();
- private static Dictionary<float, Dictionary<float, Vert>> pointVertDict = new Dictionary<float, Dictionary<float, Vert>>();
- private static Dictionary<int, Vert> indexVertDict = new Dictionary<int, Vert>();
- private static string outputClientFolder = "../RecastNavMesh/Meshes/";
- private static string outputServerFolder = "../Config/RecastNavData/ExportedObj/";
- #region 菜单主函数
- [MenuItem("ET/NavMesh/ExportSceneObj")]
- public static void ExportScene()
- {
- var triangulation = UnityEngine.AI.NavMesh.CalculateTriangulation();
- if (triangulation.indices.Length < 3)
- {
- Debug.LogError($"NavMeshExporter ExportScene Error - 场景里没有需要被导出的物体,请先用NavMesh进行Bake。");
- return;
- }
- vertList.Clear();
- faceList.Clear();
- pairList.Clear();
- vertFaceDict.Clear();
- vertPairDict.Clear();
- pointVertDict.Clear();
- indexVertDict.Clear();
- InputVertices(triangulation.vertices);
- InputTriangles(triangulation.indices, triangulation.areas);
- IndexVertsAndFaces();
- //WriteFile();
- // 导出*_internal.Obj,仅供Unity编辑器自己查看
- //WriteUnityObjFile();
- // 导出Recast可用的*.Obj文件
- WriteRecastObjFile();
- // 拷贝Obj和Bytes文件到服务器目录下 TODO 暂不需要
- //CopyObjFiles();
- Debug.Log($"NavMesh Output Info - Vertices:[{vertList.Count}] - Faces:[{faceList.Count}]");
- }
- #endregion
- #region 导出Bytes
- private static void InputVertices(Vector3[] vertices)
- {
- for (int i = 0, n = vertices.Length - 1; i <= n; i++)
- {
- var point = vertices[i];
- var x = (float) Math.Round(point.x, 2);
- var y = (float) Math.Round(point.y, 2);
- var z = (float) Math.Round(point.z, 2);
- if (!pointVertDict.ContainsKey(x))
- {
- pointVertDict.Add(x, new Dictionary<float, Vert>());
- }
- Vert vert;
- if (pointVertDict[x].ContainsKey(z))
- {
- vert = pointVertDict[x][z];
- }
- else
- {
- vert = new Vert();
- vert.x = x;
- vert.y = y;
- vert.z = z;
- pointVertDict[x][z] = vert;
- }
- indexVertDict.Add(i, vert);
- }
- }
- private static void InputTriangles(int[] indices, int[] areas)
- {
- Face face = null;
- var faceIndices = new HashSet<int>();
- for (int i = 0, n = areas.Length; i < n; i++)
- {
- var triangleIndexList = new int[3];
- var triangleVertList = new Vert[3];
- for (var j = 0; j < 3; j++)
- {
- triangleIndexList[j] = indices[i * 3 + j];
- triangleVertList[j] = indexVertDict[triangleIndexList[j]];
- }
- var vert0 = triangleVertList[0];
- var vert1 = triangleVertList[1];
- var vert2 = triangleVertList[2];
- if (vert0 == vert1 || vert1 == vert2 || vert2 == vert0)
- {
- continue;
- }
- var newFace = true;
- var area = areas[i] >= 3? areas[i] - 2 : 0;
- if (face != null && face.area == area)
- {
- for (var j = 0; j < 3; j++)
- {
- if (faceIndices.Contains(triangleIndexList[j]))
- {
- newFace = false;
- break;
- }
- }
- }
- if (newFace)
- {
- if (face != null)
- {
- InitFace(face);
- faceIndices.Clear();
- }
- face = new Face();
- face.area = area;
- }
- double x1 = vert1.x - vert0.x;
- double y1 = vert1.y - vert0.y;
- double z1 = vert1.z - vert0.z;
- double x2 = vert2.x - vert0.x;
- double y2 = vert2.y - vert0.y;
- double z2 = vert2.z - vert0.z;
- double normalA = y1 * z2 - z1 * y2;
- double normalB = z1 * x2 - x1 * z2;
- double normalC = x1 * y2 - y1 * x2;
- if (normalB < -0.000001 || 0.000001 < normalB)
- {
- var normalD = normalA + normalB + normalC;
- if (normalD > face.normalD)
- {
- face.normalA = normalA;
- face.normalB = normalB;
- face.normalC = normalC;
- face.normalD = normalD;
- }
- }
- for (var j = 0; j < 3; j++)
- {
- if (!faceIndices.Contains(triangleIndexList[j]))
- {
- faceIndices.Add(triangleIndexList[j]);
- face.verts.Add(triangleVertList[j]);
- }
- }
- }
- if (face != null)
- {
- InitFace(face);
- }
- foreach (var pair in pairList)
- {
- var firstFace = pair.firstEdgeFace;
- var secondFace = pair.secondEdgeFace;
- var firstDistance = GetDistance(firstFace.centerX - pair.centerX, firstFace.centerZ - pair.centerZ);
- var secondDistance = GetDistance(secondFace.centerX - pair.centerX, secondFace.centerZ - pair.centerZ);
- pair.distance = firstDistance + secondDistance;
- }
- }
- private static float GetDistance(float deltaX, float deltaZ)
- {
- return (float) Math.Round(Math.Sqrt((double) deltaX * (double) deltaX + (double) deltaZ * (double) deltaZ), 2);
- }
- private static void InitFace(Face face)
- {
- face.centerX = 0;
- face.centerZ = 0;
- var vertCount = face.verts.Count;
- foreach (var vert in face.verts)
- {
- face.centerX += vert.x;
- face.centerZ += vert.z;
- if (!vertFaceDict.ContainsKey(vert))
- {
- vertFaceDict.Add(vert, face);
- vertList.Add(vert);
- }
- }
- face.centerX /= vertCount;
- face.centerZ /= vertCount;
- if (face.normalB != 0)
- {
- face.normalX = (float) Math.Round(face.normalA / face.normalB, 6);
- face.normalZ = (float) Math.Round(face.normalC / face.normalB, 6);
- }
- for (int i = 0, n = vertCount - 1; i <= n; i++)
- {
- var firstVert = face.verts[i];
- var secondVert = face.verts[i == n? 0 : i + 1];
- if (!vertPairDict.ContainsKey(firstVert))
- {
- vertPairDict.Add(firstVert, new Dictionary<Vert, Pair>());
- }
- if (!vertPairDict.ContainsKey(secondVert))
- {
- vertPairDict.Add(secondVert, new Dictionary<Vert, Pair>());
- }
- if (!vertPairDict[secondVert].ContainsKey(firstVert))
- {
- var pair = new Pair();
- pair.firstEdgeFace = face;
- pair.firstEdgeIndex = i;
- vertPairDict[firstVert][secondVert] = pair;
- }
- else
- {
- var pair = vertPairDict[secondVert][firstVert];
- pair.centerX = (firstVert.x + secondVert.x) / 2;
- pair.centerZ = (firstVert.z + secondVert.z) / 2;
- pair.secondEdgeFace = face;
- pair.secondEdgeIndex = i;
- pairList.Add(pair);
- }
- }
- faceList.Add(face);
- }
- private static void IndexVertsAndFaces()
- {
- var minX = float.MaxValue;
- var maxX = float.MinValue;
- var minZ = float.MaxValue;
- var maxZ = float.MinValue;
- foreach (var vert in vertList)
- {
- if (minX > vert.x)
- {
- minX = vert.x;
- }
- if (maxX < vert.x)
- {
- maxX = vert.x;
- }
- if (minZ > vert.z)
- {
- minZ = vert.z;
- }
- if (maxZ < vert.x)
- {
- maxZ = vert.x;
- }
- }
- var hilbertX = 65535f / (maxX - minX);
- var hilbertZ = 65535f / (maxZ - minZ);
- foreach (var face in faceList)
- {
- var X = (uint) Math.Round((face.centerX - minX) * hilbertX);
- var Z = (uint) Math.Round((face.centerZ - minZ) * hilbertZ);
- var a = X ^ Z;
- var b = 0xFFFF ^ a;
- var c = 0xFFFF ^ (X | Z);
- var d = X & (Z ^ 0xFFFF);
- var A = a | (b >> 1);
- var B = (a >> 1) ^ a;
- var C = ((c >> 1) ^ (b & (d >> 1))) ^ c;
- var D = ((a & (c >> 1)) ^ (d >> 1)) ^ d;
- a = A;
- b = B;
- c = C;
- d = D;
- A = (a & (a >> 2)) ^ (b & (b >> 2));
- B = (a & (b >> 2)) ^ (b & ((a ^ b) >> 2));
- C ^= (a & (c >> 2)) ^ (b & (d >> 2));
- D ^= (b & (c >> 2)) ^ ((a ^ b) & (d >> 2));
- a = A;
- b = B;
- c = C;
- d = D;
- A = (a & (a >> 4)) ^ (b & (b >> 4));
- B = (a & (b >> 4)) ^ (b & ((a ^ b) >> 4));
- C ^= (a & (c >> 4)) ^ (b & (d >> 4));
- D ^= (b & (c >> 4)) ^ ((a ^ b) & (d >> 4));
- a = A;
- b = B;
- c = C;
- d = D;
- C ^= (a & (c >> 8)) ^ (b & (d >> 8));
- D ^= (b & (c >> 8)) ^ ((a ^ b) & (d >> 8));
- C ^= C >> 1;
- D ^= D >> 1;
- c = X ^ Z;
- d = D | (0xFFFF ^ (c | C));
- c = (c | (c << 8)) & 0x00FF00FF;
- c = (c | (c << 4)) & 0x0F0F0F0F;
- c = (c | (c << 2)) & 0x33333333;
- c = (c | (c << 1)) & 0x55555555;
- d = (d | (d << 8)) & 0x00FF00FF;
- d = (d | (d << 4)) & 0x0F0F0F0F;
- d = (d | (d << 2)) & 0x33333333;
- d = (d | (d << 1)) & 0x55555555;
- face.sortValue = (d << 1) | c;
- }
- faceList.Sort(SortComparison);
- for (int i = 0, n = vertList.Count; i < n; i++)
- {
- vertList[i].id = i;
- }
- for (int i = 0, n = faceList.Count; i < n; i++)
- {
- faceList[i].id = i;
- }
- }
- private static int SortComparison(Face a, Face b)
- {
- return a.sortValue.CompareTo(b.sortValue);
- }
- private static void WriteFile()
- {
- if (!System.IO.Directory.Exists(outputClientFolder))
- {
- System.IO.Directory.CreateDirectory(outputClientFolder);
- }
- var path = outputClientFolder + SceneManager.GetActiveScene().name + ".bytes";
- var writer = new BinaryWriter(new FileStream(path, FileMode.Create));
- writer.Write('N');
- writer.Write('a');
- writer.Write('v');
- writer.Write('M');
- writer.Write('e');
- writer.Write('s');
- writer.Write('h');
- writer.Write(VERSION);
- writer.Write(vertList.Count);
- foreach (var vert in vertList)
- {
- writer.Write(vert.x);
- writer.Write(vert.y);
- writer.Write(vert.z);
- }
- writer.Write(faceList.Count);
- foreach (var face in faceList)
- {
- writer.Write(face.area);
- writer.Write(face.normalX);
- writer.Write(face.normalZ);
- writer.Write(face.verts.Count);
- foreach (var vert in face.verts)
- {
- writer.Write(vert.id);
- }
- }
- writer.Write(pairList.Count);
- foreach (var pair in pairList)
- {
- writer.Write(pair.distance);
- writer.Write(pair.firstEdgeFace.id);
- writer.Write(pair.firstEdgeIndex);
- writer.Write(pair.secondEdgeFace.id);
- writer.Write(pair.secondEdgeIndex);
- }
- writer.Flush();
- writer.Close();
- AssetDatabase.Refresh();
- }
- #endregion
- #region 导出*_internal.Obj
- // ————————————————
- // 版权声明:本文为CSDN博主「_Captain」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- // 原文链接:https://blog.csdn.net/huutu/article/details/52672505
- private static void WriteUnityObjFile()
- {
- var path = outputClientFolder + SceneManager.GetActiveScene().name + "_internal.obj";
- StreamWriter tmpStreamWriter = new StreamWriter(path);
- NavMeshTriangulation tmpNavMeshTriangulation = UnityEngine.AI.NavMesh.CalculateTriangulation();
- //顶点
- for (int i = 0; i < tmpNavMeshTriangulation.vertices.Length; i++)
- {
- tmpStreamWriter.WriteLine("v " + tmpNavMeshTriangulation.vertices[i].x + " " + tmpNavMeshTriangulation.vertices[i].y + " " +
- tmpNavMeshTriangulation.vertices[i].z);
- }
- tmpStreamWriter.WriteLine("g pPlane1");
- //索引
- for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;)
- {
- tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i] + 1) + " " + (tmpNavMeshTriangulation.indices[i + 1] + 1) + " " +
- (tmpNavMeshTriangulation.indices[i + 2] + 1));
- i = i + 3;
- }
- tmpStreamWriter.Flush();
- tmpStreamWriter.Close();
- AssetDatabase.Refresh();
- }
- #endregion
- #region 导出Obj(Recast使用)
- // ————————————————
- // 版权声明:本文为CSDN博主「Rhett_Yuan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- // 原文链接:https://blog.csdn.net/rhett_yuan/article/details/79483387
- // https://www.cnblogs.com/koshio0219/p/12195974.html
- // http://wiki.unity3d.com/index.php?title=ObjExporter#EditorObjExporter.cs
- /// <summary>
- /// 将NavMesh里的所有物体导出成为RecastNavigation可以识别的Obj文件。July.11.2020. Liu Gang.
- /// </summary>
- private static void WriteRecastObjFile()
- {
- if (!System.IO.Directory.Exists(outputClientFolder))
- {
- System.IO.Directory.CreateDirectory(outputClientFolder);
- }
- var filename = SceneManager.GetActiveScene().name;
- var path = outputClientFolder + filename + ".obj";
- StreamWriter sw = new StreamWriter(path);
- Dictionary<string, ObjMaterial> materialList = PrepareFileWrite();
- List<MeshFilter> meshes = Collect();
- int count = 0;
- foreach (MeshFilter mf in meshes)
- {
- sw.Write("mtllib ./" + filename + ".mtl\n");
- string strMes = MeshToString(mf, materialList);
- sw.Write(strMes);
- EditorUtility.DisplayProgressBar("Exporting objects...", mf.name, count++ / (float) meshes.Count);
- }
- sw.Flush();
- sw.Close();
- EditorUtility.ClearProgressBar();
- AssetDatabase.Refresh();
- }
- // Global containers for all active mesh/terrain tags
- public static List<MeshFilter> m_Meshes = new List<MeshFilter>();
- private static string NAVMESH_TAG = "NavMesh";
- private static int vertexOffset = 0;
- private static int normalOffset = 0;
- private static int uvOffset = 0;
- public struct ObjMaterial
- {
- public string name;
- public string textureName;
- }
- private static void Clear()
- {
- vertexOffset = 0;
- normalOffset = 0;
- uvOffset = 0;
- }
- private static Dictionary<string, ObjMaterial> PrepareFileWrite()
- {
- Clear();
- return new Dictionary<string, ObjMaterial>();
- }
- public static List<MeshFilter> Collect()
- {
- List<MeshFilter> meshes = new List<MeshFilter>();
- // 确定场景内必须有NAVMESH_TAG这个tag
- // ————————————————
- // 版权声明:本文为CSDN博主「懵懵爸爸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- // 原文链接:https://blog.csdn.net/ljason1993/article/details/80924723
- bool bFindTag = false;
- string[] strTags = UnityEditorInternal.InternalEditorUtility.tags;
- foreach (string tag in strTags)
- {
- if (tag == NAVMESH_TAG)
- {
- bFindTag = true;
- break;
- }
- }
- if (!bFindTag)
- {
- Debug.LogError($"NavMeshExporter Collect Error - 所有需要被NavMesh导出的物体的Tag必须是:[{NAVMESH_TAG}],目前的项目里没有这个Tag。");
- return meshes;
- }
- MeshFilter[] meshFilters = FindObjectsOfType<MeshFilter>();
- foreach (MeshFilter mf in meshFilters)
- {
- if (mf.gameObject.tag == NAVMESH_TAG)
- {
- meshes.Add(mf);
- }
- }
- if (meshes.Count == 0)
- {
- Debug.LogError($"NavMeshExporter Collect Error - 场景里没有需要被导出的物体,需要被导出的物体,它们的Tag必须是:[{NAVMESH_TAG}]。");
- }
- return meshes;
- }
- public static string MeshToString(MeshFilter mf, Dictionary<string, ObjMaterial> materialList)
- {
- Mesh m = mf.sharedMesh;
- Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;
- StringBuilder sb = new StringBuilder();
- sb.Append("g ").Append(mf.name).Append("\n");
- // foreach(Vector3 v in m.vertices) {
- // sb.Append(string.Format("v {0} {1} {2}\n",v.x,v.y,v.z));
- // }
- foreach (Vector3 lv in m.vertices)
- {
- Vector3 wv = mf.transform.TransformPoint(lv);
- //This is sort of ugly - inverting x-component since we're in
- //a different coordinate system than "everyone" is "used to".
- sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z));
- }
- sb.Append("\n");
- // foreach(Vector3 v in m.normals) {
- // sb.Append(string.Format("vn {0} {1} {2}\n",v.x,v.y,v.z));
- // }
- foreach (Vector3 lv in m.normals)
- {
- Vector3 wv = mf.transform.TransformDirection(lv);
- sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z));
- }
- sb.Append("\n");
- foreach (Vector3 v in m.uv)
- {
- sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
- }
- int countMat = m.subMeshCount;
- if (mats == null)
- {
- Debug.LogWarning($"NavMeshExporter MeshToString Error - 没有找到材质");
- return sb.ToString();
- }
- else if (mats.Length < countMat)
- {
- Debug.LogWarning($"NavMeshExporter MeshToString Error - 共享材质数量小于该物体的子物体数量 - {mats.Length} / {countMat}");
- countMat = mats.Length;
- }
- for (int material = 0; material < countMat; material++)
- {
- string nameMat = "null";
- Texture mainTexture = null;
- if (mats[material] != null)
- {
- nameMat = mats[material].name;
- mainTexture = mats[material].mainTexture;
- }
- sb.Append("\n");
- sb.Append("usemtl ").Append(nameMat).Append("\n");
- sb.Append("usemap ").Append(nameMat).Append("\n");
- //See if this material is already in the materiallist.
- try
- {
- ObjMaterial objMaterial = new ObjMaterial();
- objMaterial.name = nameMat;
- if (mainTexture)
- objMaterial.textureName = AssetDatabase.GetAssetPath(mainTexture);
- else
- objMaterial.textureName = null;
- materialList.Add(objMaterial.name, objMaterial);
- }
- catch (ArgumentException)
- {
- //Already in the dictionary
- }
- // int[] triangles = m.GetTriangles(material);
- // for (int i=0;i<triangles.Length;i+=3) {
- // sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
- // triangles[i]+1, triangles[i+1]+1, triangles[i+2]+1));
- // }
- int[] triangles = m.GetTriangles(material);
- for (int i = 0; i < triangles.Length; i += 3)
- {
- //Because we inverted the x-component, we also needed to alter the triangle winding.
- sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n",
- triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset));
- }
- }
- vertexOffset += m.vertices.Length;
- normalOffset += m.normals.Length;
- uvOffset += m.uv.Length;
- return sb.ToString();
- }
- #endregion
- #region 拷贝文件
- /// <summary>
- /// 把生成的Obj文件拷贝到服务器
- /// https://www.cnblogs.com/wangjianhui008/p/3234519.html
- /// </summary>
- private static void CopyObjFiles()
- {
- string sourceFolder = outputClientFolder;
- // *.bytes, *.obj, *_internal.obj文件不再拷贝到服务器的Config/Navmesh目录下,不再需要了,减少服务器数据文件的大小。Aug.27.2020. Liu Gang.
- //得到原文件根目录下的所有文件
- // {
- // string[] files = System.IO.Directory.GetFiles(sourceFolder);
- // foreach (string file in files)
- // {
- // string name = System.IO.Path.GetFileName(file);
- // // 仅拷贝bytes文件和obj文件,但是不包括文件名里包含“internal”字样的obj文件。
- // var ext = Path.GetExtension(file);
- // if (ext == ".bytes" || (ext == ".obj" && !file.Contains("_internal.")))
- // {
- // string dest = System.IO.Path.Combine(destFolder, name);
- // System.IO.File.Copy(file, dest, true); //复制文件
- // }
- // }
- // }
- // 拷贝到RecastDemo配置路径
- {
- string[] files = System.IO.Directory.GetFiles(sourceFolder);
- //如果目标路径不存在,则创建目标路径
- if (!System.IO.Directory.Exists(outputServerFolder))
- {
- System.IO.Directory.CreateDirectory(outputServerFolder);
- }
- foreach (string file in files)
- {
- string name = System.IO.Path.GetFileName(file);
- // 仅拷贝bytes文件和obj文件,但是不包括文件名里包含“internal”字样的obj文件。
- var ext = Path.GetExtension(file);
- if (ext == ".obj" && !file.Contains("_internal."))
- {
- string dest = System.IO.Path.Combine(outputServerFolder, name);
- System.IO.File.Copy(file, dest, true); //复制文件
- UnityEngine.Debug.Log($"Recast:从{file}复制obj文件到{dest}成功");
- }
- }
- }
- }
- #endregion
- }
- }
|