using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// Spawns the specified prefab and positions it when a NavMeshSurface reports there's /// a new NavMesh it can walk on. Used in the ZED spatial mapping sample scene to spawn a bunny /// to walk around your environment once you're done scanning it. /// public class EnemyManager : MonoBehaviour { /// /// The prefab used to spawn the enemy. Should contain a NavMeshAgent component. /// [Tooltip("The prefab used to spawn the enemy. Should contain a NavMeshAgent component. ")] public GameObject enemyPrefab; /// /// Whether or not the NavMesh from the NavMeshSurface is ready. /// private bool isReady = false; /// /// Number of tries the script has attempted to place the prefab on the NavMesh. It stops trying at 20. /// private int noNavMeshCount = 0; /// /// Center of the current navMesh. /// private Vector3 centerNavMesh; /// /// ID of agent type accepted by the NavMesh. Agent IDs are defined in the Navigation window. /// private int agentTypeNavMeshID = 0; /// /// ID of the agent type from the prefab's NavMeshAgent component. Agent IDs are defined in the Navigation window. /// private int agentType = 0; /// /// List of all instantiated enemies. /// static List enemies = new List(); void Update() { //Try to create an enemy on the NavMesh. if (isReady && enemies.Count == 0 && noNavMeshCount < 20) { Create(); } //Clear all the empty items if (enemies.Count > 0) { enemies.RemoveAll(item => item == null); } } /// /// Called when ZEDSpatialMapping begins making a new mesh, to clear existing enemies /// and prevent the script from trying to place enemies. /// Subscribed to ZEDSpatialMapping.OnMeshStarted in OnEnable(). /// void StartNavMesh() { //Clear all the enemies Clear(); isReady = false; } private void OnEnable() { NavMeshSurface.OnNavMeshReady += Ready; //Set the ZEDLight component on the object if a light is active Component[] lights = enemyPrefab.GetComponentsInChildren(typeof(Light)); foreach (Light l in lights) { if (!l.gameObject.GetComponent()) { l.gameObject.AddComponent(); } } } private void Start() { StartNavMesh (); UnityEngine.AI.NavMeshAgent c; if ((c = enemyPrefab.GetComponent()) != null) { agentType = c.agentTypeID; } } private void OnDisable() { //Unsubscribe from the events. NavMeshSurface.OnNavMeshReady -= Ready; } /// /// Called when the NavMesh is finished being created, to clear existing data /// and begin trying to place the enemy. /// Subscribed to NavMeshSurface.OnNavMeshReady in OnEnable(). /// /// /// void Ready(object sender, NavMeshSurface.PositionEventArgs e) { centerNavMesh = e.position; isReady = e.valid; agentTypeNavMeshID = e.agentTypeID; Clear(); } public void Ready() { isReady = true; Clear(); } /// /// Destroy all the enemies and clear its container /// void Clear() { foreach (GameObject o in enemies) { Destroy(o); } enemies.Clear(); } /// /// Remove a particular GameObject /// /// static void Destroyed(GameObject o) { enemies.Remove(o); } /// /// Try to create an agent on the NavMesh. /// public void Create() { //If the agent and the NavMesh have different agent IDs, don't assign it. if (agentType != agentTypeNavMeshID) { Debug.LogWarning("The agent ID differs from the NavMesh"); return; } //Instantiate the prefab and try to place it on the NavMesh. enemies.Add(Instantiate(enemyPrefab, centerNavMesh, Quaternion.identity)); List notActivated = new List(); //For each enemy created, move it on the NavMesh. foreach (GameObject o in enemies) { NavMeshAgentController a = o.GetComponent(); if (a.Move()) { a.GetComponent().Activate(); noNavMeshCount = 0; } else { notActivated.Add(a.gameObject); noNavMeshCount++; } } //Destroy any objects that were not properly added to the NavMesh. foreach (GameObject o in notActivated) { Destroy(o); enemies.Remove(o); } } }