Exemplo n.º 1
0
        private static string GetAreaEnumValuesAsText(ref string[] areaNames)
        {
            var increment = 0;
            var output    = new StringBuilder();
            var seenKeys  = new HashSet <string>();

            foreach (var name in areaNames)
            {
                var enumKey = string.Concat(name.Where(char.IsLetterOrDigit));
                var value   = 1 << NavMesh.GetAreaFromName(name);

                output.Append(seenKeys.Contains(name)
                    ? $"{(enumKey + increment++)} = {value}, "
                    : $"{enumKey} = {value}, ");

                seenKeys.Add(enumKey);
            }
            return(output.ToString());
        }
Exemplo n.º 2
0
        void AddObstacles(List <NavMeshBuildSource> sources)
        {
            // ---------Terrain trees-- - ------

            Terrain     terrain     = Terrain.activeTerrain;
            TerrainData terrainData = terrain.terrainData;
            Vector3     size        = Terrain.activeTerrain.terrainData.size;
            Vector3     terrainPos  = terrain.GetPosition();
            //Debug.Log("terrainPos = " + terrainPos);
            int treesArea = NavMesh.GetAreaFromName("Not Walkable");

            if (treesArea < 0)
            {
                Debug.LogError("Unrecognized area name! The default area will be used instead.");
                treesArea = 0;
            }

            TreePrototype[] treePrototypes = terrainData.treePrototypes;
            TreeInstance[]  treeInstances  = terrainData.treeInstances;
            for (int i = 0; i < treeInstances.Length; i++)
            {
                //treeInstances[i] is the current ACTUAL tree we're going over.
                //the tree prototype is the "template" used by this tree.
                TreePrototype   prototype = treePrototypes[treeInstances[i].prototypeIndex];
                GameObject      prefab    = prototype.prefab;
                NavMeshObstacle obstacle  = prefab.GetComponent <NavMeshObstacle>();
                if (obstacle == null)
                {
                    continue;
                }

                //Debug.Log("treeInstances[" + i + "] info:\n" + treeInstances[i].position + " " + treeInstances[i].rotation + " " + treeInstances[i].widthScale + " " + treeInstances[i].heightScale);
                Vector3 worldTreePos = terrainPos + Vector3.Scale(treeInstances[i].position, size)
                                       + obstacle.center;
                Quaternion worldTreeRot   = Quaternion.Euler(0, treeInstances[i].rotation * Mathf.Rad2Deg, 0);
                Vector3    worldTreeScale = new Vector3(treeInstances[i].widthScale, treeInstances[i].heightScale, treeInstances[i].widthScale);
                //Debug.Log("CREATED MATRIX FOR TRS:\nworldTreePos = " + worldTreePos + "\nworldTreeRot = " + worldTreeRot + "\nworldTreeScale = " + worldTreeScale);

                NavMeshBuildSource src = new NavMeshBuildSource();
                src.transform = Matrix4x4.TRS(worldTreePos, worldTreeRot, worldTreeScale);

                switch (obstacle.shape)
                {
                case NavMeshObstacleShape.Capsule:
                    src.shape = NavMeshBuildSourceShape.Capsule;

                    //Unity 2019.2.0f1: BUG!! navMeshObstacle.height returns exactly HALF of the actual height of the obstacle.
                    //Use the size property instead.
                    src.size = obstacle.size;
                    break;

                case NavMeshObstacleShape.Box:
                    src.shape = NavMeshBuildSourceShape.Box;
                    src.size  = obstacle.size;
                    break;

                default:
                    Debug.LogError("Unsupported type of " + typeof(NavMeshObstacleShape).Name
                                   + " for the building of the " + typeof(NavMeshSurface).Name + "! (" + obstacle.shape + ")");
                    break;
                }
                src.size = Vector3.Scale(src.size, prefab.transform.localScale);
                //Debug.Log("src.size = " + src.size);
                src.area = treesArea;
                sources.Add(src);
            }

            // --- --- --- End of Terrain trees --- --- ---
        }
Exemplo n.º 3
0
        List <NavMeshBuildSource> CollectSources()
        {
            var sources = new List <NavMeshBuildSource>();
            var markups = new List <NavMeshBuildMarkup>();

            List <NavMeshModifier> modifiers;

            if (m_CollectObjects == CollectObjects.Children)
            {
                modifiers = new List <NavMeshModifier>(GetComponentsInChildren <NavMeshModifier>());
                modifiers.RemoveAll(x => !x.isActiveAndEnabled);
            }
            else
            {
                modifiers = NavMeshModifier.activeModifiers;
            }

            foreach (var m in modifiers)
            {
                if ((m_LayerMask & (1 << m.gameObject.layer)) == 0)
                {
                    continue;
                }
                if (!m.AffectsAgentType(m_AgentTypeID))
                {
                    continue;
                }
                var markup = new NavMeshBuildMarkup();
                markup.root            = m.transform;
                markup.overrideArea    = m.overrideArea;
                markup.area            = m.area;
                markup.ignoreFromBuild = m.ignoreFromBuild;
                markups.Add(markup);
            }

#if UNITY_EDITOR
            if (!EditorApplication.isPlaying)
            {
                if (m_CollectObjects == CollectObjects.All)
                {
                    UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
                        null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources);
                }
                else if (m_CollectObjects == CollectObjects.Children)
                {
                    UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
                        transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources);
                }
                else if (m_CollectObjects == CollectObjects.Volume)
                {
                    Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
                    var       worldBounds  = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size));

                    UnityEditor.AI.NavMeshBuilder.CollectSourcesInStage(
                        worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, gameObject.scene, sources);
                }
            }
            else
#endif
            {
                if (m_CollectObjects == CollectObjects.All)
                {
                    NavMeshBuilder.CollectSources(null, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
                }
                else if (m_CollectObjects == CollectObjects.Children)
                {
                    NavMeshBuilder.CollectSources(transform, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
                }
                else if (m_CollectObjects == CollectObjects.Volume)
                {
                    Matrix4x4 localToWorld = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
                    var       worldBounds  = GetWorldBounds(localToWorld, new Bounds(m_Center, m_Size));
                    NavMeshBuilder.CollectSources(worldBounds, m_LayerMask, m_UseGeometry, m_DefaultArea, markups, sources);
                }
            }

            // --- --- --- Terrain trees --- --- ---

            Terrain[] terrains = GameObject.FindObjectsOfType <Terrain>();

            if (terrains.Length > 0)
            {
                foreach (Terrain item in terrains)
                {
                    Terrain     terrain     = item.GetComponent <Terrain>();
                    TerrainData terrainData = terrain.terrainData;
                    Vector3     size        = Terrain.activeTerrain.terrainData.size;
                    Vector3     terrainPos  = terrain.GetPosition();
                    if (m_Debug)
                    {
                        Debug.Log("terrainPos = " + terrainPos);
                    }
                    int treesArea = NavMesh.GetAreaFromName("Not Walkable");
                    if (treesArea < 0)
                    {
                        Debug.LogError("Unrecognized area name! The default area will be used instead.");
                        treesArea = 0;
                    }

                    TreePrototype[] treePrototypes = terrainData.treePrototypes;
                    TreeInstance[]  treeInstances  = terrainData.treeInstances;
                    if (m_Debug)
                    {
                        Debug.Log("trees found = " + treeInstances.Length);
                    }
                    for (int i = 0; i < treeInstances.Length; i++)
                    {
                        //treeInstances[i] is the current ACTUAL tree we're going over.
                        //the tree prototype is the "template" used by this tree.
                        TreePrototype prototype = treePrototypes[treeInstances[i].prototypeIndex];
                        GameObject    prefab    = prototype.prefab;

                        NavMeshObstacle obstacle     = prefab.GetComponent <NavMeshObstacle>();
                        Collider        collider     = prefab.GetComponentInChildren <Collider>();
                        bool            obstacleBool = obstacle != null && (m_SelectionType == SelectionType.All || m_SelectionType == SelectionType.Obstacles);
                        bool            colliderBool = collider != null && (m_SelectionType == SelectionType.All || m_SelectionType == SelectionType.Colliders);
                        if (obstacleBool || colliderBool)
                        {
                            Vector3 center = Vector3.zero;
                            if (obstacle != null)
                            {
                                center = obstacle.center;
                            }
                            else if (collider != null)
                            {
                                center = collider.bounds.center;
                            }

                            if (m_Debug)
                            {
                                Debug.Log("treeInstances[" + i + "] info:\n" + treeInstances[i].position + " " + treeInstances[i].rotation + " " + treeInstances[i].widthScale + " " + treeInstances[i].heightScale);
                            }
                            Vector3 worldTreePos = terrainPos + Vector3.Scale(treeInstances[i].position, size) + center;

                            Quaternion worldTreeRot   = Quaternion.Euler(0, treeInstances[i].rotation * Mathf.Rad2Deg, 0);
                            Vector3    worldTreeScale = new Vector3(treeInstances[i].widthScale, treeInstances[i].heightScale, treeInstances[i].widthScale);
                            if (m_Debug)
                            {
                                Debug.Log("CREATED MATRIX FOR TRS:\nworldTreePos = " + worldTreePos + "\nworldTreeRot = " + worldTreeRot + "\nworldTreeScale = " + worldTreeScale);
                            }

                            NavMeshBuildSource src = new NavMeshBuildSource();
                            src.transform = Matrix4x4.TRS(worldTreePos, worldTreeRot, worldTreeScale);

                            if (obstacleBool)
                            {
                                switch (obstacle.shape)
                                {
                                case NavMeshObstacleShape.Capsule:
                                    src.shape = NavMeshBuildSourceShape.Capsule;

                                    //Unity 2019.2.0f1: BUG!! navMeshObstacle.height returns exactly HALF of the actual height of the obstacle.
                                    //Use the size property instead.
                                    src.size = obstacle.size;
                                    break;

                                case NavMeshObstacleShape.Box:
                                    src.shape = NavMeshBuildSourceShape.Box;
                                    src.size  = obstacle.size;
                                    break;

                                default:
                                    Debug.LogError("Unsupported type of " + typeof(NavMeshObstacleShape).Name
                                                   + " for the building of the " + typeof(NavMeshSurface).Name + "! (" + obstacle.shape + ")");
                                    break;
                                }
                            }
                            else if (colliderBool)
                            {
                                if (collider is CapsuleCollider)
                                {
                                    src.shape = NavMeshBuildSourceShape.Capsule;

                                    //Unity 2019.2.0f1: BUG!! navMeshObstacle.height returns exactly HALF of the actual height of the obstacle.
                                    //Use the size property instead.
                                    src.size = ((CapsuleCollider)collider).radius * Vector3.one * m_ColliderTolerance;
                                }
                                else if (collider is BoxCollider)
                                {
                                    src.shape = NavMeshBuildSourceShape.Box;
                                    src.size  = collider.bounds.size * m_ColliderTolerance;
                                }
                                else
                                {
                                    Debug.LogError("Unsupported type of " + typeof(NavMeshObstacleShape).Name
                                                   + " for the building of the " + typeof(NavMeshSurface).Name + "! (" + obstacle.shape + ")");
                                }
                            }

                            // Scale size
                            src.size = Vector3.Scale(src.size, prefab.transform.localScale);
                            if (m_Debug)
                            {
                                Debug.Log("src.size = " + src.size);
                            }
                            src.area = treesArea;
                            sources.Add(src);
                        }
                    }
                }
            }

            // --- --- --- End of Terrain trees --- --- ---

            if (m_IgnoreNavMeshAgent)
            {
                sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent <NavMeshAgent>() != null));
            }

            if (m_IgnoreNavMeshObstacle)
            {
                sources.RemoveAll((x) => (x.component != null && x.component.gameObject.GetComponent <NavMeshObstacle>() != null));
            }

            AppendModifierVolumes(ref sources);

            return(sources);
        }