# SpawnOnBake (Sample Script)

## Spawn On Bake (Sample)

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

## Purpose

Safely spawn characters or AI agents after the first successful runtime bake, avoiding errors like:

> *“Failed to create agent because there is no valid NavMesh.”*

***

## How it works

* Subscribes to `BakerEvents.OnBakeCompleted`.
* On each completed bake:
  * Chooses a spawn position (from **Spawn Point** or the GameObject this script is attached to).
  * Calls `NavMesh.SamplePosition()` to snap to a valid NavMesh point.
  * Instantiates the prefab.
* If **Only Once** is enabled, ignores subsequent bakes.

***

## Inspector

* **Prefab (GameObject)**\
  The object to spawn (e.g., enemy, NPC, player). If it’s an AI, it should include a `NavMeshAgent`.
* **Spawn Point (Transform, optional)**\
  If set, the prefab spawns here; otherwise it spawns at this component’s transform.
* **Only Once (bool)**\
  If enabled, spawns on the first completed bake only.
* **Sample Max Distance (float)**\
  Radius around the desired position to search for a valid NavMesh point.
* **Area Mask (int)**\
  NavMesh area mask for sampling (default: `NavMesh.AllAreas`).

***

## Example usage

1. Ensure your scene has a **BakerCoordinator** with a **NavMeshBakeProfile** and **Center Target**.
2. Add one or more **DynamicNavMeshSurface** components for the regions you want baked.
3. Create an empty GameObject and add **SpawnOnBake**.
4. Assign a **Prefab** (e.g., an enemy with `NavMeshAgent`).
5. Optionally assign a **Spawn Point**.
6. Press Play — once the first bake finishes, the prefab spawns on valid NavMesh.

***

## Why it’s useful

* Guarantees AI never spawns off-navmesh.
* Robust for procedural or streaming worlds where navmesh is generated at runtime.
* Demonstrates listening to `BakerEvents.OnBakeCompleted` to gate gameplay logic.

***

## Script

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

namespace MegaCrush.NavmeshBaker.Sample
{
    /// <summary>
    /// Spawns a prefab after the first completed runtime bake.
    /// Listens to BakerEvents instead of directly binding to the service.
    /// </summary>
    public sealed class SpawnOnBake : MonoBehaviour
    {
        [Header("Prefab to Spawn")]
        [SerializeField] private GameObject prefab;

        [Header("Spawn Settings")]
        [SerializeField] private Transform spawnPoint;
        [SerializeField] private bool onlyOnce = true;

        [Header("NavMesh Sampling")]
        [SerializeField, Min(0f)] private float sampleMaxDistance = 5f;
        [SerializeField] private int areaMask = NavMesh.AllAreas;

        private bool _hasSpawned;

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

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

        private void HandleBakeCompleted(DynamicNavMeshSurface surface, Bounds region, float durationSeconds)
        {
            if (!prefab) return;
            if (onlyOnce && _hasSpawned) return;

            Vector3 desired = spawnPoint ? spawnPoint.position : transform.position;

            if (NavMesh.SamplePosition(desired, out NavMeshHit hit, sampleMaxDistance, areaMask))
            {
                Instantiate(prefab, hit.position, Quaternion.identity);
                _hasSpawned = true;
#if UNITY_EDITOR
                Debug.Log($"[SpawnOnBake] Spawned '{prefab.name}' at {hit.position} (region {region.center}±{region.extents})");
#endif
            }
            else
            {
#if UNITY_EDITOR
                Debug.LogWarning($"[SpawnOnBake] No valid NavMesh within {sampleMaxDistance}m of {desired}. " +
                                 "Increase Sample Max Distance or adjust Spawn Point.");
#endif
            }
        }
    }
}
```


---

# 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/spawnonbake-sample-script.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.
