/// <summary> /// Extracts the tile data from a serialized navigation mesh. /// </summary> /// <remarks> /// <para> /// Tile data is normally preserved by serializing /// the the content of the <see cref="NavmeshTileData"/> objects used to /// create the navigation mesh. That is the most efficient method /// and should be used whenever possible. /// </para> /// <para> /// This method can be used to extract the tile data when /// the original data is not available. It should only be used as /// a backup to the normal method since this method is not efficient. /// </para> /// <para> /// Always check the header polygon count /// of the resulting <see cref="NavmeshTileExtract"/> objects before use since some tiles /// in the navigation mesh may be empty. The <see cref="NavmeshTileExtract.data"/> /// field will be null for empty tiles. /// </para> /// </remarks> /// <param name="serializedMesh">A valid serialized navigation mesh.</param> /// <param name="tileData"> /// The extracted tile data. [Length: <see cref="Navmesh.GetMaxTiles()"/>] /// </param> /// <param name="config">The navigation mesh's configuration.</param> /// <returns>The <see cref="NavStatus"/> flags for the operation.</returns> public static NavStatus ExtractTileData(byte[] serializedMesh , out NavmeshTileExtract[] tileData , out NavmeshParams config) { /* * Design notes: * * Normally, the only way to get tile data out of a navigation mesh * is when the tile data is NOT owned by the mesh. This is not * permitted for normal mesh objects, which is why the RemoveTile() method * never returns the tile data. * * The most efficient way to extract the data is to get it directly * from the serialized data. But that would be a code maintenance issue. * (Duplicating the mesh creation process.) So I'm using this rather * convoluted method instead. * */ if (serializedMesh == null) { tileData = null; config = null; return NavStatus.Failure | NavStatus.InvalidParam; } Navmesh mesh; NavStatus status = Navmesh.UnsafeCreate(serializedMesh, false, out mesh); if ((status & NavStatus.Failure) != 0) { tileData = null; config = null; return status; } config = mesh.GetConfig(); int count = mesh.GetMaxTiles(); tileData = new NavmeshTileExtract[count]; if (count == 0) return NavStatus.Sucess; for (int i = 0; i < count; i++) { NavmeshTile tile = mesh.GetTile(i); tileData[i].header = tile.GetHeader(); if (tileData[i].header.polyCount == 0) // Tile not in use. continue; tileData[i].tileRef = tile.GetTileRef(); IntPtr tdata = new IntPtr(); int tsize = 0; NavmeshEx.dtnmRemoveTile(mesh.root, tileData[i].tileRef, ref tdata, ref tsize); tileData[i].data = UtilEx.ExtractArrayByte(tdata, tsize); NavmeshEx.dtnmFreeBytes(ref tdata); } return NavStatus.Sucess; }
/// <summary> /// Extracts the tile data from a serialized navigation mesh. /// </summary> /// <remarks> /// <para> /// Tile data is normally preserved by serializing /// the the content of the <see cref="NavmeshTileData"/> objects used to /// create the navigation mesh. That is the most efficient method /// and should be used whenever possible. /// </para> /// <para> /// This method can be used to extract the tile data when /// the original data is not available. It should only be used as /// a backup to the normal method since this method is not efficient. /// </para> /// <para> /// Always check the header polygon count /// of the resulting <see cref="NavmeshTileExtract"/> objects before use since some tiles /// in the navigation mesh may be empty. The <see cref="NavmeshTileExtract.data"/> /// field will be null for empty tiles. /// </para> /// </remarks> /// <param name="serializedMesh">A valid serialized navigation mesh.</param> /// <param name="tileData"> /// The extracted tile data. [Length: <see cref="Navmesh.GetMaxTiles()"/>] /// </param> /// <param name="config">The navigation mesh's configuration.</param> /// <returns>The <see cref="NavStatus"/> flags for the operation.</returns> public static NavStatus ExtractTileData(byte[] serializedMesh , out NavmeshTileExtract[] tileData , out NavmeshParams config) { /* * Design notes: * * Normally, the only way to get tile data out of a navigation mesh * is when the tile data is NOT owned by the mesh. This is not * permitted for normal mesh objects, which is why the RemoveTile() method * never returns the tile data. * * The most efficient way to extract the data is to get it directly * from the serialized data. But that would be a code maintenance issue. * (Duplicating the mesh creation process.) So I'm using this rather * convoluted method instead. * */ if (serializedMesh == null) { tileData = null; config = null; return(NavStatus.Failure | NavStatus.InvalidParam); } Navmesh mesh; NavStatus status = Navmesh.UnsafeCreate(serializedMesh, false, out mesh); if ((status & NavStatus.Failure) != 0) { tileData = null; config = null; return(status); } config = mesh.GetConfig(); int count = mesh.GetMaxTiles(); tileData = new NavmeshTileExtract[count]; if (count == 0) { return(NavStatus.Sucess); } for (int i = 0; i < count; i++) { NavmeshTile tile = mesh.GetTile(i); tileData[i].header = tile.GetHeader(); if (tileData[i].header.polyCount == 0) { // Tile not in use. continue; } tileData[i].tileRef = tile.GetTileRef(); IntPtr tdata = new IntPtr(); int tsize = 0; NavmeshEx.dtnmRemoveTile(mesh.root, tileData[i].tileRef, ref tdata, ref tsize); tileData[i].data = UtilEx.ExtractArrayByte(tdata, tsize); NavmeshEx.dtnmFreeBytes(ref tdata); } return(NavStatus.Sucess); }