Snippets

Jesse Williams DungeonRuntimeNavigation.cs

Created by Jesse Williams last modified
//$ Copyright 2016, Code Respawn Technologies Pvt Ltd - All Rights Reserved $//
//$ Modification 2017, West Winds Creative, Developed for Labyrintheer $//

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

namespace Labyrintheer.DungeonBuilder.Navigation
{
    [System.Serializable]
    public enum DungeonNavMeshSourceType
    {
        MeshData,
        Collision
    }

    public class DungeonRuntimeNavigation : MonoBehaviour
    {
        /// <summary>
        /// Should dynamic navigation be created during runtime (For NPC AI)
        /// </summary>
        public bool enableRuntimeNavigation = false;

        public LNavAgentDataSettings[] LNavMeshAgents;

        public Vector3 boundsPadding = Vector3.zero;

        public bool landscapeBaking = true;

        DungeonNavMeshSourceType meshSourceType = DungeonNavMeshSourceType.MeshData;

        // The size of the build bounds
        Bounds dungeonBounds;

        NavMeshData[] m_NavMesh;
        AsyncOperation m_Operation;
        NavMeshDataInstance[] m_Instance;
        List<NavMeshBuildSource>[] meshSources;

        public void BuildNavMesh()
        {
            DestroyNavMesh();
            meshSources = new List<NavMeshBuildSource>[LNavMeshAgents.Length];
            m_NavMesh = new NavMeshData[LNavMeshAgents.Length];
            m_Instance = new NavMeshDataInstance[LNavMeshAgents.Length];

            if (enableRuntimeNavigation && Application.isPlaying)
            {
                Dungeon dungeon = GetComponent<Dungeon>();
                if (!dungeon)
                {
                    Debug.LogError("DungeonRuntimeNavigation should be attached to a Dungeon prefab. Missing Dungeon Script in the game object");
                    return;
                }

                for (int count = 0; count < LNavMeshAgents.Length; count++)
                {
                    m_NavMesh[count] = new NavMeshData();
                    m_Instance[count] = NavMesh.AddNavMeshData(m_NavMesh[count]);
                    meshSources[count] = new List<NavMeshBuildSource>();
                }

                dungeonBounds = DungeonUtils.GetDungeonBounds(dungeon);
                dungeonBounds.size = dungeonBounds.size + boundsPadding;

                UpdateNavMesh(false);
            }
        }

        private void DestroyNavMesh()
        {
            // Unload navmesh and clear handle
            if (m_Instance != null)
            {
                for (int count = 0; count < LNavMeshAgents.Length; count++)
                {
                    m_Instance[count].Remove();
                    m_NavMesh[count] = null;
                    meshSources[count].Clear();
                }
            }

            dungeonBounds = new Bounds();
        }

        void CollectMeshSources()
        {

            Dungeon dungeon = GetComponent<Dungeon>();
            if (!dungeon)
            {
                Debug.LogError("DungeonRuntimeNavigation should be attached to a Dungeon prefab. Missing Dungeon Script in the game object");
                return;
            }

            for (int count = 0; count < LNavMeshAgents.Length; count++)
            {
                meshSources[count].Clear();

                DungeonNavMeshSourceCollector.CollectSources(dungeon, meshSourceType, ref meshSources[count]);
            }
        }

        void UpdateNavMesh(bool asyncUpdate = false)
        {
            CollectMeshSources();

            for (int count = 0; count < LNavMeshAgents.Length; count++)
            {
                NavMeshBuildSettings defaultBuildSettings = NavMesh.GetSettingsByID(LNavMeshAgents[count].LNavAgentID);
                defaultBuildSettings.overrideTileSize = LNavMeshAgents[count].LOverrideTileSize;
                defaultBuildSettings.tileSize = LNavMeshAgents[count].LTileSize;

                if (asyncUpdate)
                {
                    m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh[count], defaultBuildSettings, meshSources[count], dungeonBounds);
                }
                else
                {
                    NavMeshBuilder.UpdateNavMeshData(m_NavMesh[count], defaultBuildSettings, meshSources[count], dungeonBounds);
                }
            }
        }

        void OnDrawGizmosSelected()
        {
            if (!enableRuntimeNavigation) return;

            if (m_NavMesh[0])
            {
                Gizmos.color = Color.green;
                Gizmos.DrawWireCube(m_NavMesh[0].sourceBounds.center, m_NavMesh[0].sourceBounds.size);
            }

            Gizmos.color = Color.green;
            var center = dungeonBounds.center;
            var size = dungeonBounds.size;
            Gizmos.DrawWireCube(center, size);
        }

        void OnDisable()
        {
            DestroyNavMesh();
        }
    }

    [System.Serializable]
    public class LNavAgentDataSettings
    {
        public int LNavAgentID;
        public bool LOverrideTileSize = false;
        public int LTileSize = 256;
    }
}

Comments (0)