### Example: Handling Pathfinding Results Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md This example demonstrates how to check the status of a pathfinding query using Succeeded() and HasAnyFlag(). It shows how to process a successful path or handle a partial result. ```csharp DtStatus status = navMeshQuery.FindPath(/*...*/); if (status.Succeeded()) { // Process path } else if (status.HasAnyFlag(DtStatus.DT_PARTIAL_RESULT)) { // Handle partial result } ``` -------------------------------- ### Example: Creating Nav Mesh Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md This example shows how to initialize DtNavMeshCreateParams with data from Recast output. It populates essential fields like vertices, polygons, and areas before calling BuildNavMeshData. ```csharp var createParams = new DtNavMeshCreateParams { verts = polyMesh.verts, vertCount = polyMesh.nvertices, polys = polyMesh.polys, polyCount = polyMesh.npolys, polyAreas = polyMesh.areas, polyFlags = polyMesh.flags, maxVertsPerPoly = polyMesh.maxVertsPerPoly, // ... set other fields from Recast output }; DtDetourBuilder.BuildNavMeshData(createParams, out var meshData); ``` -------------------------------- ### Initialize DtCrowdAgentParams Example Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/04-crowd-simulation.md Example of initializing a DtCrowdAgentParams object with specific behavior flags. Ensure all necessary flags are combined using the bitwise OR operator. ```csharp var params = new DtCrowdAgentParams { radius = 0.6f, height = 2.0f, maxAcceleration = 8.0f, maxSpeed = 5.0f, collisionQueryRange = 12.0f, pathOptimizationRange = 30.0f, updateFlags = DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_VIS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | DtCrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE, obstacleAvoidanceType = 0, separationWeight = 0.5f }; ``` -------------------------------- ### Complete NavMesh Generation Configuration Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Example demonstrating the full configuration and generation of a navigation mesh for a small indoor level using DotRecast. This includes setting up geometry, builder configuration, and initializing the nav mesh. ```csharp using DotRecast.Recast; using DotRecast.Detour; // Generate navmesh for small indoor level var geom = new RcSampleInputGeomProvider(triMesh); var config = new RcConfig( partitionType: RcPartition.WATERSHED, cellSize: 0.3f, cellHeight: 0.2f, agentMaxSlope: 45.0f, agentHeight: 2.0f, agentRadius: 0.6f, agentMaxClimb: 0.9f, regionMinSize: 8, regionMergeSize: 20, edgeMaxLen: 12.0f, edgeMaxError: 1.3f, vertsPerPoly: 6, detailSampleDist: 6.0f, detailSampleMaxError: 1.0f, filterLowHangingObstacles: true, filterLedgeSpans: true, filterWalkableLowHeightSpans: true, walkableAreaMod: RcAreaModification.Default, buildMeshDetail: true); var builder = new RcBuilder(); var results = builder.BuildTiles(geom, config, true, true, threads: 4); // Create navmesh from results var navMesh = new DtNavMesh(); var navMeshParams = new DtNavMeshParams { orig = geom.GetMeshBoundsMin(), tileWidth = 32.0f, tileHeight = 32.0f, maxTiles = 16, maxPolys = 8192 }; navMesh.Init(navMeshParams, 6); foreach (var result in results) { var createParams = new DtNavMeshCreateParams { // ... populate from result ... }; DtDetourBuilder.BuildNavMeshData(createParams, out var meshData); navMesh.AddTile(meshData, 0, 0, out _); } var navMeshQuery = new DtNavMeshQuery(navMesh); // Ready for pathfinding ``` -------------------------------- ### Tile Cache Compression Example Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Demonstrates the usage of the DtTileCacheCompressor for compressing and decompressing tile data. Ensure you have tile data to use. ```csharp var compressor = new DtTileCacheCompressor(); byte[] original = /* tile data */; byte[] compressed = compressor.Compress(original); byte[] decompressed = compressor.Decompress(compressed); ``` -------------------------------- ### Dynamic Obstacle Workflow Example Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Illustrates how to add, update, and remove dynamic obstacles in the tile cache to affect pathfinding. This requires a configured navmesh and query. ```csharp // Create tile cache var params = new DtTileCacheParams { /* config */ }; var compressor = new DtTileCacheCompressor(); var store = new DtTileCacheLayerStore(); var tileCache = new DtTileCache(params, compressor, store); // Add initial tiles tileCache.AddTile(tile1Data, tile1Data.Length, 0, out _); tileCache.AddTile(tile2Data, tile2Data.Length, 0, out _); tileCache.Update(navMesh, navMeshQuery); // Simulate obstacle (wall falls down) var obstaclePos = new RcVec3f(20, 0, 20); tileCache.AddObstacle(obstaclePos, 2.0f, 3.0f, out int obstacleId); tileCache.Update(navMesh, navMeshQuery); // Pathfinding now avoids the obstacle navMeshQuery.FindPath(startRef, endRef, startPos, endPos, filter, out var path, out int pathLen); // Obstacle is removed (wall rebuilt) tileCache.RemoveObstacle(obstacleId); tileCache.Update(navMesh, navMeshQuery); // Path updated to no longer avoid cleared area ``` -------------------------------- ### Streaming Large Worlds Example Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Demonstrates a tile streaming system that loads and unloads tiles based on player distance to manage large open-world environments. This requires a LoadTileFromDisk function. ```csharp var loadedTiles = new Dictionary<(int, int), DtCompressedTile>(); var tileSize = 32; // World units per tile void StreamTilesAroundPlayer(RcVec3f playerPos, float loadDistance) { int playerTileX = (int)(playerPos.X / tileSize); int playerTileZ = (int)(playerPos.Z / tileSize); int loadRange = (int)MathF.Ceiling(loadDistance / tileSize); // Unload distant tiles var tilesToRemove = new List<(int, int)>(); foreach (var coord in loadedTiles.Keys) { int dist = Math.Max(Math.Abs(coord.Item1 - playerTileX), Math.Abs(coord.Item2 - playerTileZ)); if (dist > loadRange) { tilesToRemove.Add(coord); } } foreach (var coord in tilesToRemove) { tileCache.RemoveTile(loadedTiles[coord].GetRef()); loadedTiles.Remove(coord); } // Load nearby tiles for (int x = playerTileX - loadRange; x <= playerTileX + loadRange; x++) { for (int z = playerTileZ - loadRange; z <= playerTileZ + loadRange; z++) { var coord = (x, z); if (!loadedTiles.ContainsKey(coord)) { byte[] tileData = LoadTileFromDisk(x, z); if (tileData != null) { tileCache.AddTile(tileData, tileData.Length, 0, out var tile); loadedTiles[coord] = tile; } } } } // Update navmesh tileCache.Update(navMesh, navMeshQuery); } ``` -------------------------------- ### DtStatus Usage Example Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/08-types-reference.md Demonstrates how to check the status of a navigation mesh query and handle different outcomes. ```csharp var status = navMeshQuery.FindPath(...); if (status.Succeeded()) { // Process path } else if (status.HasAnyFlag(DtStatus.DT_PARTIAL_RESULT)) { // Handle incomplete path } else if (status.Failed()) { // Query failed } ``` -------------------------------- ### Use Default Query Filter Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Utilize the default query filter for pathfinding, which allows traversal of all areas with uniform cost. This is a basic setup for simple path requests. ```csharp var filter = new DtQueryDefaultFilter(); // All areas traversable, uniform cost navMeshQuery.FindPath(startRef, endRef, startPos, endPos, filter, out var path, out var pathLen); ``` -------------------------------- ### Build Project with Command Prompt Source: https://github.com/ikpil/dotrecast/blob/main/BuildingAndIntegrating.md Use this command to build the entire project in release mode from the command line. Requires .NET 8 SDK. ```shell dotnet build -c Release ``` -------------------------------- ### Run Demo Application with Command Prompt Source: https://github.com/ikpil/dotrecast/blob/main/BuildingAndIntegrating.md Execute the DotRecast.Recast.Demo application using the dotnet CLI. Specify the project, framework, and configuration. ```shell dotnet run --project src/DotRecast.Recast.Demo --framework net8.0 -c Release ``` -------------------------------- ### Linear Interpolation Between Two Vectors Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/01-core-numerics.md Performs linear interpolation between two 3D vectors. The 'amount' parameter controls the position along the line segment between the start and end vectors, where 0 yields the start vector and 1 yields the end vector. ```csharp var start = new RcVec3f(0.0f, 0.0f, 0.0f); var end = new RcVec3f(10.0f, 0.0f, 0.0f); var mid = RcVec3f.Lerp(start, end, 0.5f); // Returns (5.0f, 0, 0) ``` -------------------------------- ### DtCrowdAgent.SetTarget Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/04-crowd-simulation.md Sets a navigation target for an agent, guiding it towards a specified position on the navigation mesh. ```APIDOC ## DtCrowdAgent.SetTarget ### Description Sets a navigation target for an agent, guiding it towards a specified position on the navigation mesh. ### Method ```csharp public bool SetTarget(long polyRef, RcVec3f targetPos) ``` ### Endpoint N/A (Method Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **polyRef** (long) - Required - The reference to the navigation mesh polygon containing the target - **targetPos** (RcVec3f) - Required - The target position within the specified polygon ### Returns - **bool** - True if the target was successfully set, false otherwise. ### Request Example ```csharp var agent = crowd.GetAgent(agentId); var targetPos = new RcVec3f(20, 0, 20); // Find the polygon containing the target navMeshQuery.FindNearestPoly(targetPos, extents, filter, out var targetRef, out var targetPt); if (agent.SetTarget(targetRef, targetPt)) { Console.WriteLine("Target set"); } ``` ``` -------------------------------- ### Initialize DtDynNavMesh with Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Instantiate DtDynNavMesh by providing configuration parameters like dimensions and tile sizes. ```csharp var navMeshParams = new DtDynNavMeshParams { width = 48, height = 48, tileWidth = 32.0f, tileHeight = 32.0f }; var dynNavMesh = new DtDynNavMesh(navMeshParams); ``` -------------------------------- ### Create RcOffMeshConnection Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Defines an off-mesh connection with start and end points, radius, flags, and area type. ```csharp var ladder = new RcOffMeshConnection { start = new[] { new RcVec3f(5, 0, 5) }, end = new[] { new RcVec3f(5, 5, 5) }, radius = 0.3f, flags = 1, area = RcAreas.RC_WALKABLE_AREA }; ``` -------------------------------- ### Initialize DtTileCache Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Demonstrates the creation of a DtTileCache instance with specified parameters, compressor, and storage. This is the first step to using the tile cache system. ```csharp var params = new DtTileCacheParams(); params.orig = new RcVec3f(0, 0, 0); params.cs = 0.3f; params.ch = 0.2f; params.width = 48; params.height = 48; params.maxTiles = 128; params.maxObstacles = 128; var compressor = new DtTileCacheCompressor(); var store = new DtTileCacheLayerStore(); var tileCache = new DtTileCache(params, compressor, store); ``` -------------------------------- ### RcAreas Usage Example for Area Modification Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/08-types-reference.md Shows how to create an RcAreaModification to assign a custom traversal cost to a specific area, like water. ```csharp // Mark water region with 2x traversal cost var waterMod = new RcAreaModification(RcAreas.RC_WATER_AREA, 2); volume.area = waterMod; ``` -------------------------------- ### RcAtomicInteger Operations Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/08-types-reference.md Provides thread-safe atomic operations for integers. Includes methods for getting, setting, incrementing, decrementing, and adding values atomically. ```csharp public class RcAtomicInteger { public int Get(); public void Set(int value); public int IncrementAndGet(); public int DecrementAndGet(); public int AddAndGet(int delta); public int GetAndSet(int newValue); } ``` -------------------------------- ### Save and Load Navmesh Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Demonstrates how to save a DtNavMesh to a binary file and load it back using DtMeshSetWriter and DtMeshSetReader. ```csharp // Save using (var file = File.Create("navmesh.bin")) using (var writer = new BinaryWriter(file)) { var meshSetWriter = new DtMeshSetWriter(); meshSetWriter.Write(writer, navMesh); } // Load var loadedNavMesh = new DtNavMesh(); using (var file = File.OpenRead("navmesh.bin")) using (var reader = new BinaryReader(file)) { var meshSetReader = new DtMeshSetReader(); meshSetReader.Read(reader, loadedNavMesh); } ``` -------------------------------- ### Copy RcVec3f to Float Array Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/01-core-numerics.md Copies the components of an RcVec3f vector into a float array starting at a specified index. Useful for data serialization or interoperability. ```csharp var v = new RcVec3f(1.0f, 2.0f, 3.0f); float[] values = new float[10]; v.CopyTo(values, 2); // values[2]=1, values[3]=2, values[4]=3 ``` -------------------------------- ### Object Pooling Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Shows how to use an object pool for efficient object management, including renting and returning objects. ```csharp var pool = new RcObjectPool(); var obj = pool.Rent(); try { // Use obj } finally { pool.Return(obj); } ``` -------------------------------- ### Initialize and Build Dynamic NavMesh with Geometry Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Initialize the dynamic navmesh system and add static level geometry. This is the first step before building the initial navigation mesh. ```csharp using DotRecast.Detour.Dynamic; // Initialize dynamic navmesh var navMeshParams = new DtDynNavMeshParams { width = 48, height = 48, tileWidth = 32.0f, tileHeight = 32.0f }; var dynNavMesh = new DtDynNavMesh(navMeshParams); // Add static level geometry float[] levelVerts = /* level geometry vertices */; int[] levelTris = /* level geometry triangles */; dynNavMesh.AddVoxelGeometry(levelVerts, levelVerts.Length / 3, levelTris, levelTris.Length / 3); // Build initial navmesh var config = new DtDynNavMeshConfig { cellSize = 0.3f, cellHeight = 0.2f, agentHeight = 2.0f, agentRadius = 0.6f, agentMaxSlope = 45.0f, agentMaxClimb = 0.9f }; var status = dynNavMesh.Build(config, out var navMesh); var navMeshQuery = new DtNavMeshQuery(navMesh); ``` -------------------------------- ### Crowd Simulation Initialization and Agent Management Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/04-crowd-simulation.md Initializes a crowd simulation, adds multiple agents with specified parameters, and sets navigation targets for each agent. Requires a valid navMesh and navMeshQuery. ```csharp using DotRecast.Detour.Crowd; // Initialize var crowd = new DtCrowd(32, 0.6f, navMesh); var filter = new DtQueryDefaultFilter(); // Add agents var agentIds = new List(); for (int i = 0; i < 10; i++) { var pos = new RcVec3f(i * 2, 0, 0); var params = new DtCrowdAgentParams { radius = 0.6f, height = 2.0f, maxAcceleration = 8.0f, maxSpeed = 5.0f }; int agentId = crowd.AddAgent(pos, params); if (agentId >= 0) { agentIds.Add(agentId); } } // Set target for each agent foreach (var agentId in agentIds) { var targetPos = new RcVec3f(50, 0, 50); navMeshQuery.FindNearestPoly(targetPos, new RcVec3f(2, 10, 2), filter, out var targetRef, out var targetPt); var agent = crowd.GetAgent(agentId); agent.SetTarget(targetRef, targetPt); } ``` -------------------------------- ### Find Path Between Points Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Finds a path between two points on a loaded navmesh using DtNavMeshQuery. It first finds the nearest polygons for the start and end points, then calculates the path. ```csharp var navMeshQuery = new DtNavMeshQuery(navMesh); var filter = new DtQueryDefaultFilter(); // Find nearest polygons for start and end points navMeshQuery.FindNearestPoly(startPos, extents, filter, out var startRef, out var startPt); navMeshQuery.FindNearestPoly(endPos, extents, filter, out var endRef, out var endPt); // Find path var status = navMeshQuery.FindPath(startRef, endRef, startPos, endPos, filter, out var path, out var pathLen); if (status.Succeeded()) { // Get simplified waypoint path navMeshQuery.GetStraightPath(startPos, endPos, path, pathLen, out var waypoints, out var waypointCount, 64); // Use waypoints for movement for (int i = 0; i < waypointCount; i++) { Console.WriteLine($"Waypoint {i}: {waypoints[i]}"); } } ``` -------------------------------- ### Build Navmesh from Configuration Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Generate the final navmesh using a detailed configuration object. This process combines static geometry and dynamic objects. ```csharp var config = new DtDynNavMeshConfig { cellSize = 0.3f, cellHeight = 0.2f, agentHeight = 2.0f, agentRadius = 0.6f, agentMaxSlope = 45.0f, agentMaxClimb = 0.9f, regionMinSize = 8, regionMergeSize = 20, edgeMaxLen = 12.0f, edgeMaxError = 1.3f, vertsPerPoly = 6 }; var status = dynNavMesh.Build(config, out var navMesh); if (status.Succeeded()) { Console.WriteLine("Navmesh built"); } ``` -------------------------------- ### Find Nearest Polygon Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md Locates the closest polygon to a given point within a specified search area. Use this to find a starting polygon for pathfinding or to determine the nearest navigable surface. ```csharp public DtStatus FindNearestPoly( RcVec3f center, RcVec3f halfExtents, IDtQueryFilter filter, out long nearestRef, out RcVec3f nearestPt) ``` ```csharp var queryPt = new RcVec3f(5, 2, 5); var searchRadius = new RcVec3f(2, 10, 2); var filter = new DtQueryDefaultFilter(); navMeshQuery.FindNearestPoly(queryPt, searchRadius, filter, out var nearestRef, out var nearestPt); if (nearestRef != 0) { Console.WriteLine($"Found polygon at {nearestPt}"); } ``` -------------------------------- ### Manage Interactive Obstacles with Dynamic NavMesh Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Demonstrates adding, updating, and removing dynamic objects like crates, and rebuilding the navmesh to reflect these changes for pathfinding. ```csharp // During gameplay, player pushes a crate var crateRef = dynNavMesh.AddObject( new RcVec3f(10, 0.5f, 10), new RcVec3f(0.5f, 0.5f, 0.5f), RcAreas.RC_WALKABLE_AREA, 0, out var _); // Rebuild navmesh to avoid crate status = dynNavMesh.Build(config, out navMesh); navMesh = navMeshQuery.GetNavMesh(); // Pathfinding now avoids crate navMeshQuery.FindPath(startRef, endRef, startPos, endPos, filter, out var path, out int pathLen); // Player moves the crate dynNavMesh.UpdateObject(crateRef, new RcVec3f(15, 0.5f, 10), new RcVec3f(0.5f, 0.5f, 0.5f)); // Rebuild with new crate position status = dynNavMesh.Build(config, out navMesh); // Player removes the crate dynNavMesh.RemoveObject(crateRef); status = dynNavMesh.Build(config, out navMesh); ``` -------------------------------- ### Configure Walking NPC Agent Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Define parameters for a standard walking NPC, prioritizing lower speeds and simpler pathfinding optimizations. ```csharp var npcParams = new DtCrowdAgentParams { radius = 0.5f, height = 1.8f, maxAcceleration = 2.0f, maxSpeed = 1.4f, // ~3 mph walk speed collisionQueryRange = 10.0f, pathOptimizationRange = 20.0f, separationWeight = 0.5f, obstacleAvoidanceType = 0, updateFlags = DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_VIS }; ``` -------------------------------- ### Run Unit Tests with Command Prompt Source: https://github.com/ikpil/dotrecast/blob/main/BuildingAndIntegrating.md Execute all unit tests for the project using the dotnet CLI. Ensures all modules function correctly. ```shell dotnet test --framework net8.0 -c Release ``` -------------------------------- ### Query Filters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Demonstrates the usage of default and empty query filters, and notes the possibility of custom filter implementation. ```csharp var filter = new DtQueryDefaultFilter(); var emptyFilter = new DtQueryEmptyFilter(); // Custom: implement IDtQueryFilter ``` -------------------------------- ### Build Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Generates the navmesh from the current static voxels and dynamic objects, using the provided configuration. ```APIDOC ## Build ### Description Generates the navmesh from the current static voxels and dynamic objects, using the provided configuration. ### Parameters #### Path Parameters - **config** (DtDynNavMeshConfig) - Required - Build configuration - **navMesh** (out DtNavMesh) - Required - Output navmesh ### Returns `DtStatus` — Success or error ### Request Example ```csharp var config = new DtDynNavMeshConfig { cellSize = 0.3f, cellHeight = 0.2f, agentHeight = 2.0f, agentRadius = 0.6f, agentMaxSlope = 45.0f, agentMaxClimb = 0.9f, regionMinSize = 8, regionMergeSize = 20, edgeMaxLen = 12.0f, edgeMaxError = 1.3f, vertsPerPoly = 6 }; var status = dynNavMesh.Build(config, out var navMesh); if (status.Succeeded()) { Console.WriteLine("Navmesh built"); } ``` ``` -------------------------------- ### RcConfig Constructor (Basic) Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Initializes RcConfig with essential parameters for navigation mesh generation, including partition type, voxel dimensions, agent properties, and region/edge settings. ```csharp public RcConfig( RcPartition partitionType, float cellSize, float cellHeight, float agentMaxSlope, float agentHeight, float agentRadius, float agentMaxClimb, int regionMinSize, int regionMergeSize, float edgeMaxLen, float edgeMaxError, int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans, RcAreaModification walkableAreaMod, bool buildMeshDetail) ``` -------------------------------- ### Configure DtTileCache Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Shows how to set up the DtTileCacheParams struct with essential configuration values like origin, cell size, tile dimensions, and agent properties. This configuration is vital for correct navmesh generation and behavior. ```csharp var params = new DtTileCacheParams { orig = new RcVec3f(0, 0, 0), cs = 0.3f, ch = 0.2f, width = 48, height = 48, maxTiles = 128, maxObstacles = 128, walkableHeight = 2.0f, walkableRadius = 0.6f, walkableClimb = 0.9f }; ``` -------------------------------- ### Create and Use RcSampleInputGeomProvider Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Instantiate a geometry provider with raw triangle mesh data. This is the default implementation for wrapping geometry. ```csharp var triMesh = new RcTriMesh(vertices, triangles); var geomProvider = new RcSampleInputGeomProvider(triMesh); ``` -------------------------------- ### Instantiate RcBuilder Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Create an instance of RcBuilder to begin navigation mesh generation. An optional progress listener can be provided for build updates. ```csharp var builder = new RcBuilder(); // Or with progress tracking: var builder = new RcBuilder(new MyProgressListener()); ``` -------------------------------- ### Initialize DtCrowd Manager Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/04-crowd-simulation.md Creates a new DtCrowd instance to manage agents. Requires an initialized DtNavMesh. ```csharp var navMesh = /* initialized DtNavMesh */; var crowd = new DtCrowd( maxAgents: 32, maxAgentRadius: 0.6f, nav: navMesh); ``` -------------------------------- ### Configure Small Creature Agent Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Define parameters for small, agile creatures, prioritizing high acceleration and speed relative to their size, with moderate avoidance settings. ```csharp var critterParams = new DtCrowdAgentParams { radius = 0.2f, height = 0.5f, maxAcceleration = 12.0f, maxSpeed = 4.0f, // Proportionally fast collisionQueryRange = 5.0f, pathOptimizationRange = 10.0f, separationWeight = 0.3f, obstacleAvoidanceType = 1, updateFlags = DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | DtCrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE }; ``` -------------------------------- ### Complete Navmesh Save/Load Cycle Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/07-io-serialization.md Demonstrates saving a generated navmesh to a file and then loading it back. Ensure the navmesh is initialized and populated before saving. The loaded navmesh can be used for pathfinding queries. ```csharp using DotRecast.Detour; using DotRecast.Detour.Io; // Generate or build navmesh var navMesh = new DtNavMesh(); // ... initialize and add tiles ... // Save to file string filePath = "my_level.navmesh"; using (var file = File.Create(filePath)) using (var writer = new BinaryWriter(file)) { var meshSetWriter = new DtMeshSetWriter(); var status = meshSetWriter.Write(writer, navMesh); if (status.Succeeded()) { Console.WriteLine("Navmesh saved"); } } // Load from file var loadedNavMesh = new DtNavMesh(); using (var file = File.OpenRead(filePath)) using (var reader = new BinaryReader(file)) { var meshSetReader = new DtMeshSetReader(); var status = meshSetReader.Read(reader, loadedNavMesh); if (status.Succeeded()) { Console.WriteLine("Navmesh loaded"); // Use loaded navmesh for queries var navMeshQuery = new DtNavMeshQuery(loadedNavMesh); // ... pathfinding ... } } ``` -------------------------------- ### Recast Configuration Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Instantiate RcConfig with various parameters for navmesh generation. Use tiled configuration for large environments. ```csharp var config = new RcConfig( partitionType: RcPartition.WATERSHED, cellSize: 0.3f, cellHeight: 0.2f, agentMaxSlope: 45.0f, agentHeight: 2.0f, agentRadius: 0.6f, agentMaxClimb: 0.9f, regionMinSize: 8, regionMergeSize: 20, edgeMaxLen: 12.0f, edgeMaxError: 1.3f, vertsPerPoly: 6, detailSampleDist: 6.0f, detailSampleMaxError: 1.0f, filterLowHangingObstacles: true, filterLedgeSpans: true, filterWalkableLowHeightSpans: true, walkableAreaMod: RcAreaModification.Default, buildMeshDetail: true); // For tiled config: var tiledConfig = new RcConfig( useTiles: true, tileSizeX: 32, tileSizeZ: 32, borderSize: 3, partition: RcPartition.WATERSHED, cellSize: 0.3f, // ... other parameters ); ``` -------------------------------- ### Implement IRcBuilderProgressListener Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Callback interface for build progress updates during mesh generation. Implement this to receive progress notifications. ```csharp public class MyProgressListener : IRcBuilderProgressListener { public void OnProgress(int completed, int total) { float percent = (float)completed / total * 100; Console.WriteLine($"Build progress: {percent:F1}%"); } } var builder = new RcBuilder(new MyProgressListener()); ``` -------------------------------- ### DtDynNavMesh Constructor Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Initializes a new instance of the DtDynNavMesh class with specified configuration parameters. ```APIDOC ## DtDynNavMesh Constructor ### Description Initializes a new instance of the DtDynNavMesh class with specified configuration parameters. ### Parameters #### Path Parameters - **params** (DtDynNavMeshParams) - Required - Configuration parameters ### Request Example ```csharp var navMeshParams = new DtDynNavMeshParams { width = 48, height = 48, tileWidth = 32.0f, tileHeight = 32.0f }; var dynNavMesh = new DtDynNavMesh(navMeshParams); ``` ``` -------------------------------- ### Select Partitioning Method Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Choose a partitioning method for generating navigation meshes. WATERSHED is robust for complex geometry, MONOTONE is faster for simple terrain, and LAYERS supports multi-level maps. ```csharp RcPartition.WATERSHED ``` ```csharp RcPartition.MONOTONE ``` ```csharp RcPartition.LAYERS ``` -------------------------------- ### Initialize Empty DtNavMesh Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md Initializes an empty navigation mesh with specified parameters. Ensure the status is checked for success. ```csharp var navMesh = new DtNavMesh(); var param = new DtNavMeshParams { orig = new RcVec3f(0, 0, 0), tileWidth = 32.0f, tileHeight = 32.0f, maxTiles = 256, maxPolys = 16384 }; var status = navMesh.Init(param, 6); if (status.Failed()) { Console.WriteLine("Failed to initialize navmesh"); } ``` -------------------------------- ### Initialize DtDynNavMeshParams Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Define the initialization parameters for a DtDynNavMesh, including dimensions, tile sizes, and maximum vertices per polygon. ```csharp var params = new DtDynNavMeshParams { width = 48, height = 48, tileWidth = 32.0f, tileHeight = 32.0f, maxVertsPerPoly = 6 }; ``` -------------------------------- ### Configure Navigation Mesh for Indoor Level Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Use standard indoor settings for cell size and height when generating navigation meshes for indoor environments. ```csharp var config = new RcConfig( partitionType: RcPartition.WATERSHED, cellSize: 0.3f, // Standard indoor cellHeight: 0.2f, agentMaxSlope: 45.0f, agentHeight: 2.0f, agentRadius: 0.6f, agentMaxClimb: 0.9f, // ... ); ``` -------------------------------- ### Configure Humanoid Player Agent Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Set parameters for a typical player character, balancing speed, acceleration, and collision avoidance for a humanoid form. ```csharp var playerParams = new DtCrowdAgentParams { radius = 0.6f, height = 2.0f, maxAcceleration = 8.0f, maxSpeed = 5.34f, // ~12 mph run speed collisionQueryRange = 12.0f, // 2× maxSpeed pathOptimizationRange = 30.0f, // Lookahead distance separationWeight = 0.5f, obstacleAvoidanceType = 0, updateFlags = DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_VIS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | DtCrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE }; ``` -------------------------------- ### DtNavMesh Initialization Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md Initializes a new navigation mesh. Two constructors are available: one for an empty mesh with parameters, and another to initialize with pre-built mesh data. ```APIDOC ## DtNavMesh Navigation mesh data structure containing tiles of polygons. Manages loaded navmesh tiles and tile lifecycle. ### Initialization Methods #### Init(in DtNavMeshParams param, int maxVertsPerPoly) Initialize a navmesh with parameters for an empty mesh. **Parameters:** - **param** (DtNavMeshParams) - Required - Navigation mesh parameters - **maxVertsPerPoly** (int) - Required - Maximum vertices per polygon **Returns:** `DtStatus` — Success or error status **Example:** ```csharp var navMesh = new DtNavMesh(); var param = new DtNavMeshParams { orig = new RcVec3f(0, 0, 0), tileWidth = 32.0f, tileHeight = 32.0f, maxTiles = 256, maxPolys = 16384 }; var status = navMesh.Init(param, 6); if (status.Failed()) { Console.WriteLine("Failed to initialize navmesh"); } ``` #### Init(DtMeshData data, int maxVertsPerPoly, int flags) Initialize with pre-built mesh data. **Parameters:** - **data** (DtMeshData) - Required - Pre-built mesh tile data - **maxVertsPerPoly** (int) - Required - Maximum vertices per polygon - **flags** (int) - Required - Tile flags **Returns:** `DtStatus` — Success or error status ``` -------------------------------- ### Configure Dynamic NavMesh Properties Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/06-dynamic-navmesh.md Set various properties to define the voxel cell size, agent characteristics, region merging, and partitioning strategy for the dynamic navmesh. ```csharp var config = new DtDynNavMeshConfig { cellSize = 0.3f, cellHeight = 0.2f, agentHeight = 2.0f, agentRadius = 0.6f, agentMaxSlope = 45.0f, agentMaxClimb = 0.9f, regionMinSize = 8, regionMergeSize = 20, edgeMaxLen = 12.0f, edgeMaxError = 1.3f, vertsPerPoly = 6, partition = RcPartition.WATERSHED }; ``` -------------------------------- ### DtNavMeshQuery Constructor and Path Planning Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/03-detour-pathfinding.md Initializes the DtNavMeshQuery with a navigation mesh and provides methods for path planning between points on the mesh. ```APIDOC ## DtNavMeshQuery Query interface for pathfinding, point location, and spatial queries against a navigation mesh. ### Constructor ```csharp public DtNavMeshQuery(DtNavMesh nav) ``` **Parameters:** - **nav** (DtNavMesh) - Navigation mesh to query **Example:** ```csharp var navMesh = /* initialized DtNavMesh */; var navMeshQuery = new DtNavMeshQuery(navMesh); ``` ### Path Planning Methods #### FindPath() Find a path between two points constrained to the navigation mesh. **Parameters:** - **startRef** (long) - Required - Polygon reference at start - **endRef** (long) - Required - Target polygon reference - **startPos** (RcVec3f) - Required - Start position in world space - **endPos** (RcVec3f) - Required - End position in world space - **filter** (IDtQueryFilter) - Required - Polygon traversal filter - **path** (out long[]) - N/A - Ordered polygon references from start to end - **pathCount** (out int) - N/A - Number of polygons in path **Returns:** `DtStatus` — DT_SUCCESS if complete path found, DT_PARTIAL_RESULT if incomplete **Example:** ```csharp var startPos = new RcVec3f(0, 0, 0); var endPos = new RcVec3f(10, 0, 10); // First, find which polygons contain these points navMeshQuery.FindNearestPoly(startPos, extents, filter, out var startRef, out _); navMeshQuery.FindNearestPoly(endPos, extents, filter, out var endRef, out _); // Then find path DtStatus status = navMeshQuery.FindPath( startRef, endRef, startPos, endPos, filter, out var path, out int pathCount); if (status.Succeeded()) { Console.WriteLine($"Path has {pathCount} polygons"); } ``` ``` -------------------------------- ### I/O Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/INDEX.md APIs for saving and loading navigation mesh data. ```APIDOC ## I/O ### `DtMeshSetWriter.Write()` #### Description Save the navigation mesh data to a file. ### `DtMeshSetReader.Read()` #### Description Load navigation mesh data from a file. ``` -------------------------------- ### Add Navmesh Tile to Cache Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Shows how to add a pre-built compressed navmesh tile to the DtTileCache. This is essential for loading parts of the navmesh into memory. ```csharp byte[] tileData = /* compressed tile from file */; var status = tileCache.AddTile(tileData, tileData.Length, 0, out var tile); if (status.Succeeded()) { Console.WriteLine("Tile loaded"); } ``` -------------------------------- ### Build Tiled Navigation Mesh Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Generates a tiled navigation mesh for large environments using BuildTiles. Requires geometry provider and configuration. Intermediate results and build-all options can be specified. ```csharp var geom = new RcSampleInputGeomProvider(geometry); var config = new RcConfig(/* parameters */); var results = builder.BuildTiles(geom, config, true, true, 4); foreach (var result in results) { if (result.GetPolyMesh() != null) { // Process successful tile result } } ``` -------------------------------- ### Configure Navigation Mesh for Small Creatures Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Use finer cell size and height, adjust agent properties for smaller dimensions, and allow for steeper slopes when configuring for small creatures like AI rats or insects. ```csharp var config = new RcConfig( cellSize: 0.15f, // Finer detail needed cellHeight: 0.1f, agentMaxSlope: 60.0f, // Can climb steep surfaces agentHeight: 0.5f, // ~1.5' tall agentRadius: 0.2f, // ~0.6' wide agentMaxClimb: 0.3f, // Small step height // ... ); ``` -------------------------------- ### RcConfig Constructor (Tiled) Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Initializes RcConfig for tiled navigation mesh generation, specifying tile dimensions, border size, and all parameters from the basic constructor. ```csharp public RcConfig( bool useTiles, int tileSizeX, int tileSizeZ, int borderSize, RcPartition partition, float cellSize, float cellHeight, float agentMaxSlope, float agentHeight, float agentRadius, float agentMaxClimb, float minRegionArea, float mergeRegionArea, float edgeMaxLen, float edgeMaxError, int vertsPerPoly, float detailSampleDist, float detailSampleMaxError, bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans, RcAreaModification walkableAreaMod, bool buildMeshDetail) ``` -------------------------------- ### RcConfig.CalcBorder() Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/02-recast-generation.md Calculates the recommended border size for navigation mesh generation based on agent radius and cell size. ```APIDOC ## RcConfig.CalcBorder() ### Description Calculates recommended border size based on agent radius. ### Method `public static int CalcBorder(float agentRadius, float cs)` ### Parameters #### Path Parameters - **agentRadius** (float) - Agent radius (world units) - **cs** (float) - Cell size (world units) ### Returns `int` — Recommended border size in voxels ### Example ```csharp int border = RcConfig.CalcBorder(0.6f, 0.3f); // Returns 5 ``` ``` -------------------------------- ### Modify Navmesh Dynamically Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Demonstrates adding static geometry, dynamic objects, and updating the navmesh in real-time. ```csharp var dynNavMesh = new DtDynNavMesh(new DtDynNavMeshParams { /* ... */ }); // Add static geometry dynNavMesh.AddVoxelGeometry(vertices, vertCount, triangles, triCount); // Add dynamic objects int objRef = dynNavMesh.AddObject(center, halfExtents, area, flags, out _); // Build navmesh var config = new DtDynNavMeshConfig { /* ... */ }; dynNavMesh.Build(config, out var navMesh); // Move object dynNavMesh.UpdateObject(objRef, newCenter, halfExtents); dynNavMesh.Build(config, out navMesh); ``` -------------------------------- ### Configure Fast Moving Enemy Agent Parameters Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/09-configuration-guide.md Set parameters for fast-moving enemies, emphasizing high speed, acceleration, and more aggressive obstacle avoidance. ```csharp var enemyParams = new DtCrowdAgentParams { radius = 0.4f, height = 1.5f, maxAcceleration = 10.0f, maxSpeed = 8.0f, // ~18 mph sprint collisionQueryRange = 15.0f, pathOptimizationRange = 40.0f, separationWeight = 0.7f, // More aggressive avoidance obstacleAvoidanceType = 1, // Higher avoidance level updateFlags = DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_VIS | DtCrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO | DtCrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE }; ``` -------------------------------- ### Handle Dynamic Obstacles Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/00-quick-reference.md Manages dynamic obstacles in the navmesh using DtTileCache. Obstacles can be added and removed at runtime, and the navmesh is updated accordingly. ```csharp var tileCache = new DtTileCache(params, new DtTileCacheCompressor(), store); // Add obstacle at runtime var status = tileCache.AddObstacle(obstaclePos, radius: 0.5f, height: 2f, out int obsRef); // Update navmesh tileCache.Update(navMesh, navMeshQuery); // Remove obstacle tileCache.RemoveObstacle(obsRef); tileCache.Update(navMesh, navMeshQuery); ``` -------------------------------- ### RcContext Class for Logging Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/08-types-reference.md Provides a context for build telemetry and logging. Use the Log method with categories like RC_LOG_PROGRESS, RC_LOG_WARNING, or RC_LOG_ERROR. ```csharp public class RcContext { public void Log(RcLogCategory category, string message); } ``` -------------------------------- ### RcContext Class Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/08-types-reference.md Provides a context for build telemetry and logging during the Recast process. It allows for logging messages categorized by progress, warnings, or errors. ```APIDOC ## RcContext Class ### Description Build telemetry and logging context. ### Methods - `Log(RcLogCategory category, string message)`: Logs a message with a specified category. ### Categories - `RC_LOG_PROGRESS` - `RC_LOG_WARNING` - `RC_LOG_ERROR` ### Source `DotRecast.Core` ``` -------------------------------- ### Tile Cache Compression Interface Source: https://github.com/ikpil/dotrecast/blob/main/_autodocs/05-tile-cache-streaming.md Defines the interface for tile data compression and decompression. Implement this to provide custom compression algorithms. ```csharp public interface IDtTileCacheCompressor { byte[] Compress(byte[] data); byte[] Decompress(byte[] data); } ```