Substitute for navmesh?

My map is 1800 by 1800, and it’s procedurally generated so I have to bake objects with navmesh at runtime. Every time I try to bake the objects after I created them my game crashes. So does anyone know a good subsitute for navmesh?

(Code just in case you want to see it)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[System.Serializable]
public class LevelZeroMap : MonoBehaviour
{
    public List<GameObject> tiles = new List<GameObject>();
    public Transform player;
    public int tileRadius;
    public GameObject doorTile;
    public float doorTileSpawnRate = 0.01f;
    public float newTileRate = 2;
    public Vector3 frontTilePos;
    public Vector3 backTilePos;
    public List<GameObject> entities = new List<GameObject>();
    public float entitySpawnRate = 0.001f;
    public float occludeDistance;
    public NavMeshSurface surface;

    private int lastIndex;
    private List<GameObject> startingTiles = new List<GameObject>();
    private Vector3[] rotations = {new Vector3(0, 90, 0), new Vector3(0, -90, 0), new Vector3(0, 0, 0), new Vector3(0, 180, 0)};
    private Vector3 oldPos;
    private List<GameObject> occlude = new List<GameObject>();
    private int enemies;
    private int escapes;

    private void Start()
    {
        for ( int i = 0; i < tileRadius; i++ )
        {
            int index = Random.Range(0, tiles.Count);
           
            while ( index == lastIndex )
            {
                index = Random.Range(0, tiles.Count);
            }
           
            lastIndex = index;

            float offset = 7.5f;

            if ( i % 2 == 0 )
            {
                offset = -offset;
            }

            GameObject tile = Instantiate(tiles[index], new Vector3(0, -2, offset * i), Quaternion.identity);

            startingTiles.Add(tile);

            ChangeTile(tile, false);
        }

        SpawnTiles();

        if ( escapes < 1 )
        {
            Transform t = occlude[Random.Range(0, occlude.Count)].transform;

            Instantiate(doorTile, t.position, t.rotation);

            Destroy(t.gameObject);

            escapes++;
        }

        surface.BuildNavMesh();

        if ( enemies < 1 )
        {
            Transform t = occlude[Random.Range(0, occlude.Count)].transform;

            int index = Random.Range(0, entities.Count - 1);

            occlude.Add(Instantiate(entities[index], t.position + new Vector3(0, -1.78f, 0), Quaternion.identity));

            enemies++;

            Destroy(t);
        }
    }

    private void Update()
    {  
        foreach ( GameObject obj in occlude )
        {
            if ( obj != null )
            {
                obj.SetActive(Vector3.Distance(obj.transform.position, player.position) < occludeDistance);
            }
        }
    }

    void ChangeTile(GameObject tile, bool isEscape)
    {
        Transform walls = tile.transform.Find("Walls");

        Quaternion rotation = Quaternion.Euler(rotations[Random.Range(0, 4)]);

        if ( walls )
        {
            if ( Random.value < 0.7 && !isEscape)
            {
                Destroy(walls.GetChild(Random.Range(0, walls.childCount)).gameObject);
            }

            if ( Random.value < 0.7 && walls.childCount > 0 && !isEscape)
            {
                Destroy(walls.GetChild(Random.Range(0, walls.childCount)).gameObject);
            }

            walls.rotation = rotation;
        }

        if ( Random.Range(0.0000f, 1.0000f) < entitySpawnRate )
        {
            int index = Random.Range(0, entities.Count - 1);

            occlude.Add(Instantiate(entities[index], tile.transform.position + new Vector3(0, -1.78f, 0), Quaternion.identity));

            enemies++;
        }

        if ( isEscape )
        {
            escapes++;
        }

        occlude.Add(tile);
    }

    void SpawnTiles()
    {
        foreach ( GameObject tile in startingTiles )
        {
            for ( int i = 1; i < tileRadius * 1.5f; i++ )
            {
                int index = Random.Range(0, tiles.Count);
                int offset = 5;

                if ( i % 2 == 0 )
                {
                    offset = -offset;
                }

                while ( index == lastIndex )
                {
                    index = Random.Range(0, tiles.Count);
                }

                lastIndex = index;

                GameObject copy;
                bool isEscape = false;

                if ( Random.Range(0.00000f, 1.00000f) < doorTileSpawnRate)
                {
                    copy = Instantiate(doorTile, new Vector3(offset * i, -2, tile.transform.position.z), Quaternion.identity);
                    isEscape = true;
                }

                else
                {
                    copy = Instantiate(tiles[index], new Vector3(offset * i, -2, tile.transform.position.z), Quaternion.identity);
                }

                ChangeTile(copy, isEscape);

            }
        }
    }
}

Depending on the type of game you’re making, grid-based A* pathfinding can be a good option. Look for A-star implementations, there’s a few around.

1 Like

Does it really crash or is it just a long lag time to build?

Find out by making your world 18x18

If it still crashes, now you have an ultra simple place to iterate until you find out why you are crashing.