using System; using System.Collections.Generic; using System.IO; using System.Linq; using DotRecast.Core.Numerics; using DotRecast.Detour; using DotRecast.Recast.Geom; using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset.Builder; using JNGame.Map.DotRecast.Util; using JNGame.Math; using UnityEngine; using UnityEngine.AI; namespace JNGame.Map.DotRecast { public class DotRecastController : MonoBehaviour { public LayerMask layerMask; private Mesh debugMesh; private DtNavMesh dtNavMesh; private List debugPathMeshs; public void Save() { if (debugMesh is null) { Debug.Log("[DotRecast] 未生成地形 请生成地形."); return; } var data = new MeshData(debugMesh); File.WriteAllText(UnityEngine.Application.dataPath + "/Resources/map1.json", JsonUtility.ToJson(data)); Debug.Log("[DotRecast] 保存成功."); } public void Load() { debugMesh = this.Merge(); var data = new MeshData(debugMesh); var vertices = new LFloat[data.vertices.Length * 3]; for (int i = 0; i < data.vertices.Length; ++i) { vertices[i * 3 + 0] = (LFloat)data.vertices[i].x; vertices[i * 3 + 1] = (LFloat)data.vertices[i].y; vertices[i * 3 + 2] = (LFloat)data.vertices[i].z; } var bmin = RcVecUtils.Create(vertices); var bmax = RcVecUtils.Create(vertices); for (int i = 1; i < vertices.Length / 3; i++) { bmin = RcVecUtils.Min(bmin, vertices, i * 3); bmax = RcVecUtils.Max(bmax, vertices, i * 3); } var geom = new DefaultInputGeomProvider(vertices,data.triangles); var builder = new TileNavMeshBuilder(); var settings = new RcNavMeshBuildSettings(); settings.cellSize = (LFloat)1f; var result = builder.Build(geom, settings); dtNavMesh = result.NavMesh; debugPathMeshs = new List(); for (int i = 0; i < dtNavMesh.GetMaxTiles(); ++i) { DtMeshTile tile = dtNavMesh.GetTile(i); if (tile != null && tile.data != null) { DrawMeshTile(tile); } } Debug.Log("[DotRecast] 加载完成."); } private void DrawMeshTile(DtMeshTile tile) { List vertices = new List(); //Begin(DebugDrawPrimitives.TRIS); for (int i = 0; i < tile.data.header.polyCount; ++i) { DtPoly p = tile.data.polys[i]; if (p.GetPolyType() == DtPolyTypes.DT_POLYTYPE_OFFMESH_CONNECTION) { continue; } if (tile.data.detailMeshes != null) { DtPolyDetail pd = tile.data.detailMeshes[i]; for (int j = 0; j < pd.triCount; ++j) { int t = (pd.triBase + j) * 4; for (int k = 0; k < 3; ++k) { int v = tile.data.detailTris[t + k]; if (v < p.vertCount) { vertices.Add(new Vector3(tile.data.verts[p.verts[v] * 3], tile.data.verts[p.verts[v] * 3 + 1] + 0.1f, tile.data.verts[p.verts[v] * 3 + 2])); } else { vertices.Add(new Vector3(tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3], tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3 + 1], tile.data.detailVerts[(pd.vertBase + v - p.vertCount) * 3 + 2])); } } } } } List vertices3 = new List(); for (int i = 0; i < vertices.Count; i += 3) { vertices3.Add(new []{vertices[i], vertices[i + 1], vertices[i + 2]}); } int triCount = vertices3.Count; Vector3[] verts = new Vector3[3 * triCount]; int[] tris = new int[3* triCount]; Color[] colors = new Color[3*triCount]; for (int i=0;i(true).Where(mf => ((1 << mf.gameObject.layer) & layerMask) > 0).ToArray(); //创建一个新的合并后的网格 Mesh mergedMesh = new Mesh(); //创建一个合并用的网格数组 CombineInstance[] combine = new CombineInstance[meshFilters.Length+1]; for (int i = 0; i < meshFilters.Length; i++) { //设置合并用的网格数组 combine[i].mesh = meshFilters[i].sharedMesh; combine[i].transform = meshFilters[i].transform.localToWorldMatrix; } var triangulation = NavMesh.CalculateTriangulation(); combine[^1].mesh = new Mesh() { vertices = triangulation.vertices, triangles = triangulation.indices, }; combine[^1].transform = Matrix4x4.identity; //合并网格 mergedMesh.CombineMeshes(combine); mergedMesh.RecalculateNormals(); mergedMesh.RecalculateBounds(); debugPathMeshs = null; return mergedMesh; } public void OnDrawGizmos() { // if (debugMesh is not null) // { // Gizmos.color = new Color(0f, 1f, 1f, 0.5f); // Gizmos.DrawMesh(debugMesh); // Gizmos.color = new Color(0f, 0f, 0f, 0.3f); // Gizmos.DrawWireMesh(debugMesh); // } // // return; if (debugPathMeshs is not null) { foreach (var mesh in debugPathMeshs) { Gizmos.color = new Color(0f, 1f, 1f, 0.5f); Gizmos.DrawMesh(mesh); } } } } }