### Install NavMeshPlus via Package Manager Source: https://context7.com/h8man/navmeshplus/llms.txt Add NavMeshPlus to your Unity project using the Package Manager by specifying its Git URL in the manifest.json file. ```json { "dependencies": { "com.h8man.2d.navmeshplus": "https://github.com/h8man/NavMeshPlus.git#master" } } ``` -------------------------------- ### Create Custom NavMesh Build Sources with NavMeshExtension Source: https://context7.com/h8man/navmeshplus/llms.txt Extend NavMeshExtension to inject custom NavMeshBuildSource entries, modify bake volume, or post-process sources. This example injects a fixed-size box as a walkable region. ```csharp using NavMeshPlus.Components; using NavMeshPlus.Extensions; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; // Inject a custom walkable box at a fixed world position into every bake. public class CustomRegionExtension : NavMeshExtension { [SerializeField] Bounds customRegion = new Bounds(Vector3.zero, new Vector3(5f, 5f, 0.1f)); [SerializeField, NavMeshArea] int regionArea = 0; // Walkable protected override void Awake() { Order = 0; // run after RootSources2d (-1000) but before default extensions base.Awake(); } public override void CollectSources( NavMeshSurface surface, List sources, NavMeshBuilderState navMeshState) { var src = new NavMeshBuildSource { shape = NavMeshBuildSourceShape.Box, transform = Matrix4x4.Translate(customRegion.center), size = customRegion.size, area = regionArea }; sources.Add(src); Debug.Log($"[CustomRegionExtension] Injected 1 custom source. Total: {sources.Count}"); } public override void CalculateWorldBounds( NavMeshSurface surface, List sources, NavMeshBuilderState navMeshState) { // Ensure the bake volume covers the custom region navMeshState.worldBounds.Encapsulate(customRegion); } } ``` -------------------------------- ### Setup 2D NavMesh with CollectSources2d Source: https://context7.com/h8man/navmeshplus/llms.txt Configures a NavMeshSurface for 2D by adding the CollectSources2d extension and setting appropriate collection geometry. Ensure the GameObject has a NavMeshSurface component. ```csharp using NavMeshPlus.Components; using NavMeshPlus.Extensions; using UnityEngine; [RequireComponent(typeof(NavMeshSurface))] public class Setup2DNavMesh : MonoBehaviour { void Awake() { var surface = GetComponent(); // Rotate surface to face a top-down 2D camera (x=-90, y=0, z=0) transform.rotation = Quaternion.Euler(270f, 0f, 0f); // Attach the 2D collector extension var collector = gameObject.AddComponent(); // Use Physics Colliders instead of sprite meshes for obstacle geometry surface.useGeometry = NavMeshCollectGeometry.PhysicsColliders; // For hexagonal tilemaps: override every tile with a hexagon mesh prefab // collector.overrideByGrid = true; // collector.useMeshPrefab = hexPrefab; // Compress tilemap bounds before collecting (avoids empty-cell padding) collector.compressBounds = true; surface.BuildNavMesh(); } } ``` -------------------------------- ### Bake NavMesh Async at Runtime Source: https://github.com/h8man/navmeshplus/wiki/HOW-TO Call BuildNavMeshAsync on the NavigationSurface component to bake NavMesh at runtime asynchronously. This is typically called in the Start() method. ```csharp public NavMeshSurface Surface2D; void Start() { Surface2D.BuildNavMeshAsync(); } ``` -------------------------------- ### Add NavMeshPlus to Unity Project via Package Manager Source: https://github.com/h8man/navmeshplus/blob/master/README.md To use NavMeshPlus, add the package to your Unity project's manifest.json file. Ensure Git is installed and added to your system's PATH. ```json "com.h8man.2d.navmeshplus": "https://github.com/h8man/NavMeshPlus.git#master" ``` -------------------------------- ### Disable NavMeshAgent Rotation Source: https://github.com/h8man/navmeshplus/wiki/HOW-TO Add this to the Start method of your NavMeshAgent scripts to prevent unwanted rotation when the game starts. This is useful for 2D games where agent rotation might be undesirable. ```csharp void Start() { var agent = GetComponent(); agent.updateRotation = false; agent.updateUpAxis = false; } ``` -------------------------------- ### NavMeshAgent Destination Drift Workaround Source: https://github.com/h8man/navmeshplus/wiki/HOW-TO Use this workaround when the NavMeshAgent gets stuck moving on the Y-axis or when setting agent.velocity has no effect if x=0. It adjusts the destination slightly on the X-axis to prevent straight vertical movement. ```C# satic float agentDrift = 0.0001f; // minimal void SetDestination(GameObject target) { if(Mathf.abs(transform.position.x - target.transform.position.x) < agentDrift) var driftPos = target.transform.position + new Vector3(agentDrift, 0f, 0f); agent.SetDestination(driftPos); } ``` -------------------------------- ### Runtime NavMesh Building with NavMeshSurface Source: https://context7.com/h8man/navmeshplus/llms.txt Demonstrates synchronous, asynchronous, and incremental baking of NavMesh data at runtime using NavMeshSurface. Preferred for runtime use to avoid frame hitches. ```csharp using NavMeshPlus.Components; using UnityEngine; using UnityEngine.AI; public class RuntimeNavMeshBuilder : MonoBehaviour { [SerializeField] NavMeshSurface surface; // ----- synchronous bake (editor or simple runtime use) ----- void BakeSync() { // Collect geometry from all objects in the scene that have NavMeshModifier, // then build and activate the NavMeshData immediately. surface.BuildNavMesh(); Debug.Log("Bake complete. Agent type: " + surface.agentTypeID); } // ----- async bake (preferred for runtime: no frame hitch) ----- async void Start() { // Disable 3-D rotation updates so the agent stays flat in 2D surface.collectObjects = CollectObjects.All; surface.useGeometry = NavMeshCollectGeometry.RenderMeshes; AsyncOperation op = surface.BuildNavMeshAsync(); while (!op.isDone) await System.Threading.Tasks.Task.Yield(); Debug.Log("Async bake complete"); } // ----- incremental update (dynamic world) ----- void UpdateOnChange() { // Rebuild nav mesh data without re-creating the NavMeshData asset, // which keeps existing NavMeshAgent paths valid during the update. surface.UpdateNavMesh(surface.navMeshData); } // ----- manual data lifecycle ----- void Reload() { surface.RemoveData(); // detach current data from the NavMesh world surface.navMeshData = null; surface.BuildNavMesh(); surface.AddData(); // re-attach to the NavMesh world } // ----- query active surfaces ----- void ListSurfaces() { foreach (var s in NavMeshSurface.activeSurfaces) Debug.Log(s.gameObject.name + " bounds: " + s.CalculateWorldBounds(new System.Collections.Generic.List())); } } ``` -------------------------------- ### Manual NavMesh Bake with NavMeshBuilderState Source: https://context7.com/h8man/navmeshplus/llms.txt Demonstrates a manual NavMesh bake process using NavMeshBuilderState. Ensure NavMeshBuilderState is used within a 'using' block to properly release cached mesh resources. ```csharp using NavMeshPlus.Extensions; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class ManualBakeExample : MonoBehaviour { void Bake() { // NavMeshBuilderState is IDisposable — wrap in using to release cached meshes using var state = new NavMeshBuilderState(); // Retrieve (or lazily create) typed sub-state shared between extensions var builder2d = state.GetExtraState(); builder2d.defaultArea = 0; // Walkable builder2d.layerMask = ~0; builder2d.agentID = 0; builder2d.CollectGeometry = NavMeshCollectGeometry.RenderMeshes; var sources = new List(); NavMeshBuilder2d.CollectSources(sources, builder2d); state.worldBounds = new Bounds(Vector3.zero, new Vector3(20f, 20f, 1f)); var settings = NavMesh.GetSettingsByID(0); var data = NavMeshBuilder.BuildNavMeshData( settings, sources, state.worldBounds, Vector3.zero, Quaternion.identity); if (data != null) NavMesh.AddNavMeshData(data); Debug.Log($ ``` -------------------------------- ### Create NavMeshLink for Off-Mesh Connections Source: https://context7.com/h8man/navmeshplus/llms.txt Use NavMeshLink to create directed or bidirectional connections between NavMesh surfaces. Configure start/end points, width, bidirectionality, cost modifier, and area. Enable autoUpdate for dynamic environments. ```csharp using NavMeshPlus.Components; using UnityEngine; public class DoorLink : MonoBehaviour { NavMeshLink link; void Start() { link = gameObject.AddComponent(); // Connect two points 5 units apart in 2D (Z used as "depth" in XY plane) link.startPoint = new Vector3(-2.5f, 0f, 0f); link.endPoint = new Vector3( 2.5f, 0f, 0f); link.width = 1f; // agent-width clearance link.bidirectional = true; link.costModifier = -1; // inherit area cost link.area = 0; // Walkable // Automatically recompute if this GameObject moves (e.g. moving platform) link.autoUpdate = true; } // Force immediate refresh after programmatic position change void MoveLink(Vector3 newPos) { transform.position = newPos; link.UpdateLink(); } } ``` -------------------------------- ### Add NavMeshPlus via Git URL in Unity Source: https://github.com/h8man/navmeshplus/blob/master/README.md Alternatively, you can add NavMeshPlus directly from its Git URL through Unity's Package Manager. Navigate to 'Package Manager', click '+', select 'Add Package from git URL', and paste the provided URL. ```bash https://github.com/h8man/NavMeshPlus.git ``` -------------------------------- ### Incremental Runtime Cache for Dynamic Objects Source: https://context7.com/h8man/navmeshplus/llms.txt Use CollectSourcesCache2d to manage dynamic NavMesh sources at runtime. It allows O(1) addition, update, and removal of sources after an initial bake, avoiding full scene rescans. Ensure it's on the same GameObject as NavMeshSurface. ```csharp using NavMeshPlus.Components; using NavMeshPlus.Extensions; using UnityEngine; using System.Collections; public class DynamicTileManager : MonoBehaviour { [SerializeField] NavMeshSurface surface; CollectSourcesCache2d cache; IEnumerator Start() { // CollectSourcesCache2d must be on the same GameObject as NavMeshSurface cache = surface.GetComponent(); // Initial full bake populates the cache var op = surface.BuildNavMeshAsync(); yield return op; Debug.Log($ ``` -------------------------------- ### Custom NavMesh Data Update Source: https://github.com/h8man/navmeshplus/wiki/HOW-TO For more control over runtime NavMesh updates and CPU optimization, use the internal NavMeshBuilder.UpdateNavMeshDataAsync method with your own caching mechanism. ```csharp NavMeshBuilder.UpdateNavMeshDataAsync(data, GetBuildSettings(), sources, sourcesBounds); ``` -------------------------------- ### Update NavMesh at Runtime Source: https://github.com/h8man/navmeshplus/wiki/HOW-TO Use UpdateNavMesh to update the NavMesh at runtime without rebuilding it from scratch every frame. This method does not cache collected sources between updates. ```csharp public NavMeshSurface Surface2D; void Update() { Surface2D.UpdateNavMesh(Surface2D.navMeshData); } ``` -------------------------------- ### Restrict NavMesh Bake Sources with RootSources2d Source: https://context7.com/h8man/navmeshplus/llms.txt Use RootSources2d to limit NavMesh baking to specific GameObjects, reducing bake times and providing precise control. Ensure `collectObjects` is set to `CollectObjects.Children` when using this extension. ```csharp using NavMeshPlus.Components; using NavMeshPlus.Extensions; using UnityEngine; using System.Collections.Generic; public class ScopedNavMeshBake : MonoBehaviour { [SerializeField] NavMeshSurface surface; [SerializeField] GameObject levelLayout; // contains floor/wall sprites [SerializeField] GameObject dynamicObjects; // spawned obstacles void Start() { var roots = surface.GetComponent(); if (roots == null) roots = surface.gameObject.AddComponent(); // Only these two hierarchies are scanned — not the entire scene roots.RootSources = new List { levelLayout, dynamicObjects }; surface.collectObjects = CollectObjects.Children; // required when using roots surface.BuildNavMesh(); Debug.Log("Bake scoped to specified root objects"); } } ``` -------------------------------- ### NavMeshModifierVolume for Volume-Based Area Override Source: https://context7.com/h8man/navmeshplus/llms.txt Applies a NavMesh area override within a specified axis-aligned box volume. Useful for painting zones like 'slow' or 'water' without modifying individual tiles. Check the count of active volumes using `NavMeshModifierVolume.activeModifiers`. ```csharp using NavMeshPlus.Components; using UnityEngine; public class SlowZoneSetup : MonoBehaviour { void Start() { var vol = gameObject.AddComponent(); // Cover a 10×10 unit 2D region centred on this GameObject vol.center = Vector3.zero; vol.size = new Vector3(10f, 10f, 0.1f); // thin Z for 2D // Custom area index 3 = "Slow" (configured in Navigation window) vol.area = 3; // Confirm the volume is registered Debug.Log("Active volumes: " + NavMeshModifierVolume.activeModifiers.Count); } } ``` -------------------------------- ### Reactive Tilemap NavMesh Cache Source: https://context7.com/h8man/navmeshplus/llms.txt Employ CollectTilemapSourcesCache2d for automatic NavMesh updates when tiles change on a Tilemap. This extension requires NavMeshModifier and NavMeshModifierTilemap on the same GameObject as the Tilemap. It listens for tilemapTileChanged events (Unity 2022.2+) for automatic source area updates. ```csharp using NavMeshPlus.Components; using NavMeshPlus.Extensions; using UnityEngine; using UnityEngine.Tilemaps; using System.Collections; public class LiveTilemapNavMesh : MonoBehaviour { [SerializeField] NavMeshSurface surface; [SerializeField] Tilemap targetTilemap; [SerializeField] TileBase wallTile; CollectTilemapSourcesCache2d tilemapCache; IEnumerator Start() { // Setup: Tilemap GameObject needs NavMeshModifier + NavMeshModifierTilemap // + CollectTilemapSourcesCache2d (can be added via Inspector or code) tilemapCache = targetTilemap.GetComponent(); // Full initial bake — populates the tile position lookup yield return surface.BuildNavMeshAsync(); // Now paint a wall tile — tilemapTileChanged fires automatically // and CollectTilemapSourcesCache2d updates the source area in its list. targetTilemap.SetTile(new Vector3Int(1, 1, 0), wallTile); // Submit the updated source list to the NavMesh without a full rescan yield return tilemapCache.UpdateNavMesh(); Debug.Log("Tile placed and NavMesh updated"); } } ``` -------------------------------- ### NavMeshModifier for Per-Object Area Override Source: https://context7.com/h8man/navmeshplus/llms.txt Marks a GameObject as a NavMesh source and overrides its navigation area. Use `ignoreFromBuild` to temporarily exclude an object from baking. Access active modifiers via `NavMeshModifier.activeModifiers`. ```csharp using NavMeshPlus.Components; using UnityEngine; public class DynamicObstacle : MonoBehaviour { NavMeshModifier modifier; void Start() { modifier = gameObject.AddComponent(); // Mark this sprite as Not Walkable (area index 1 by default) modifier.overrideArea = true; modifier.area = 1; // 1 = Not Walkable in Unity's default area table // Restrict to a specific agent type (0 = Humanoid by default) // Leave default (-1) to affect all agent types. } // Temporarily exclude from next bake without destroying the component void Hide() { modifier.ignoreFromBuild = true; FindObjectOfType().BuildNavMesh(); } // Query all active modifiers at runtime void DebugModifiers() { foreach (var m in NavMeshModifier.activeModifiers) Debug.Log($"{m.gameObject.name} overrideArea={m.overrideArea} area={m.area}"); } } ``` -------------------------------- ### Configure NavMeshModifierTilemap for Tile-Based Area Overrides Source: https://context7.com/h8man/navmeshplus/llms.txt Utilize NavMeshModifierTilemap to assign different NavMesh area types to specific tile types on a Tilemap. Ensure a NavMeshModifier component is present on the same GameObject. Cache modifiers after changes for the mapping to take effect. ```csharp using NavMeshPlus.Components; using UnityEngine; using UnityEngine.Tilemaps; public class TilemapAreaSetup : MonoBehaviour { [SerializeField] Tilemap tilemap; [SerializeField] TileBase grassTile; [SerializeField] TileBase waterTile; void Start() { // Requires NavMeshModifier on the same GameObject var modifier = tilemap.gameObject.AddComponent(); modifier.overrideArea = false; // let per-tile overrides take precedence var tilemapModifier = tilemap.gameObject.AddComponent(); // TileModifier is a public serializable struct — assign via Inspector or code // In Inspector: expand the TileModifiers list and assign tiles + areas. // At runtime you may query: if (tilemapModifier.TryGetTileModifier(new Vector3Int(3, 4, 0), tilemap, out var tileModifier)) { Debug.Log($ ``` -------------------------------- ### Override NavMeshAgent Rotation for 2D with AgentOverride2d Source: https://context7.com/h8man/navmeshplus/llms.txt AgentOverride2d disables default 3D rotation for NavMeshAgent, suitable for 2D sprite-based games. It allows custom rotation strategies to be plugged in via an IAgentOverride delegate. ```csharp using NavMeshPlus.Extensions; using UnityEngine; using UnityEngine.AI; public class Player2D : MonoBehaviour { NavMeshAgent agent; AgentOverride2d agentOverride; void Awake() { agent = GetComponent(); // AgentOverride2d suppresses 3D rotation updates agentOverride = gameObject.AddComponent(); // Option A: instant rotation toward next waypoint gameObject.AddComponent(); // Option B: smooth rotation (replace AgentRotate2d with AgentRotateSmooth2d) // var smooth = gameObject.AddComponent(); // smooth.angularSpeed = 180f; // degrees per second } void Update() { if (Input.GetMouseButtonDown(0)) { var worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); worldPos.z = 0f; agent.SetDestination(worldPos); } // Anti-drift fix for pre-Unity 6: ensure x never equals target x exactly // float agentDrift = 0.0001f; // if (Mathf.Abs(transform.position.x - target.x) < agentDrift) // destination.x += agentDrift; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.