# Click To Move (Sample)

**Namespace**: `MegaCrush.NavmeshBaker.Sample`

***

### Purpose

A simple player controller that moves an agent to the clicked point on the ground — **but only after the navmesh is ready**.\
This prevents errors like:

> *“Resume can only be called on an active agent that has been placed on a NavMesh.”*

***

### How it works

* Subscribes to `BakerEvents.OnBakeCompleted`.
* On the first bake:
  * Enables the `NavMeshAgent`.
  * Warps the agent to a valid NavMesh point near its current position.
  * Unlocks input handling.
* On each left mouse click:
  * Casts a ray into the scene.
  * Uses `NavMesh.SamplePosition()` to find the nearest walkable point.
  * Calls `SetDestination()` on the agent.

***

### Inspector

* **Ray Distance (float)**\
  Max distance for the raycast from the camera.
* **Ray Mask (LayerMask)**\
  Which layers are valid for the click raycast.
* **Sample Radius (float)**\
  Radius around the click point to look for a valid NavMesh.
* **Verbose (bool)**\
  If enabled, prints debug logs when snapping and moving.

***

### Example usage

1. Ensure your scene has a **BakerCoordinator** with a **NavMeshBakeProfile** and **Center Target**.
2. Add one or more **DynamicNavMeshSurface** components to define navigable regions.
3. Create a capsule or character GameObject.
4. Add a `NavMeshAgent` and this **ClickToMoveController** script.
5. Play — after the first runtime bake, click anywhere on the ground to move the agent.

***

### Why it’s useful

* Ensures agents only start moving once the navmesh is valid.
* Removes startup warnings/errors from spawning before a bake.
* Demonstrates how to use `BakerEvents.OnBakeCompleted` to gate gameplay logic.

***

### Script

```csharp
using UnityEngine;
using UnityEngine.AI;
using MegaCrush.RuntimeNavmeshBaker; // BakerEvents

namespace MegaCrush.NavmeshBaker.Sample
{
    [RequireComponent(typeof(NavMeshAgent))]
    public class ClickToMoveController : MonoBehaviour
    {
        [Header("Raycast")]
        [SerializeField] private float rayDistance = 1000f;
        [SerializeField] private LayerMask rayMask = ~0;

        [Header("NavMesh")]
        [SerializeField, Min(0f)] private float sampleRadius = 4f;

        [Header("Debug")]
        [SerializeField] private bool verbose = false;

        private NavMeshAgent agent;
        private Camera mainCam;
        private bool inputEnabled;

        private void Awake()
        {
            agent = GetComponent<NavMeshAgent>();
            mainCam = Camera.main;

            // Leave disabled until we can snap it to the navmesh
            agent.enabled = false;
        }

        private void OnEnable()
        {
            BakerEvents.OnBakeCompleted += HandleBakeCompleted;

            // Try immediately — scene may already have a navmesh
            if (!agent.enabled) TryEnableOnNavMesh();
        }

        private void OnDisable()
        {
            BakerEvents.OnBakeCompleted -= HandleBakeCompleted;
        }

        private void Update()
        {
            if (!mainCam) mainCam = Camera.main;
            if (!mainCam || !agent.enabled || !inputEnabled || !agent.isOnNavMesh) return;

            if (Input.GetMouseButtonDown(0))
            {
                var ray = mainCam.ScreenPointToRay(Input.mousePosition);
                if (Physics.Raycast(ray, out var hit, rayDistance, rayMask, QueryTriggerInteraction.Ignore))
                {
                    if (NavMesh.SamplePosition(hit.point, out var nmHit, sampleRadius, NavMesh.AllAreas))
                    {
                        if (verbose) Debug.Log($"[ClickToMove] SetDestination {nmHit.position}");
                        agent.isStopped = false;
                        agent.SetDestination(nmHit.position);
                    }
                    else if (verbose)
                    {
                        Debug.Log("[ClickToMove] No navmesh near click.");
                    }
                }
            }
        }

        private void HandleBakeCompleted(DynamicNavMeshSurface s, Bounds b, float dur)
        {
            if (TryEnableOnNavMesh())
            {
                // Only needed once; stop listening
                BakerEvents.OnBakeCompleted -= HandleBakeCompleted;
                if (verbose) Debug.Log("[ClickToMove] First bake detected; input enabled.");
            }
        }

        /// <summary>
        /// If there’s a valid navmesh near our position, enable the agent and warp it.
        /// </summary>
        private bool TryEnableOnNavMesh()
        {
            if (agent.enabled) return true;

            if (NavMesh.SamplePosition(transform.position, out var hit, sampleRadius, NavMesh.AllAreas))
            {
                agent.enabled = true;
                agent.Warp(hit.position);
                inputEnabled = true;

                if (verbose) Debug.Log($"[ClickToMove] Snapped agent to navmesh at {hit.position}");
                return true;
            }

            return false;
        }
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://megacrush.gitbook.io/megacrush-unity-assets/runtime-navmesh-baker/runtime-navmesh-baker-user-manual/installing-samples/click-to-move-sample.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
