/// <summary>
 /// Pause the game if the escape key is pressed.
 /// </summary>
 private void Update()
 {
     // Pause the game when escape is pressed.
     if (Input.GetKeyDown(KeyCode.Escape))
     {
         Paused = true;
     }
     timer            -= Time.deltaTime;
     timerDisplay.text = ((int)timer).ToString();
     if (timer <= 0f)
     {
         Scoreboard.EndGame();
         timer = timeLimit;
     }
 }
        /// <summary>
        /// Instantiates a new deathmatch player.
        /// </summary>
        /// <param name="availableLocations">A list of locations that the agent can spawn at.</param>
        /// <param name="prefab">The prefab that can spawn.</param>
        /// <param name="name">The name of the player.</param>
        /// <param name"teamIndex">The index of the team that the player is on.</param>
        /// <returns>The instantiated object.</returns>
        private GameObject InstantiatePlayer(List <Transform> availableLocations, GameObject prefab, string name, int teamIndex)
        {
            // Determine a unique spawn point. Team games will always start with spawn locations for the specific team so the spawn index can be 0 for consistant player spawning.
            var spawnIndex = m_TeamGame ? 0 : Random.Range(0, availableLocations.Count);
            var spawnPoint = availableLocations[spawnIndex];

            availableLocations.RemoveAt(spawnIndex);

            // Instantiate the player and notify the scoreboard.
            var player = GameObject.Instantiate(prefab, spawnPoint.position, spawnPoint.rotation) as GameObject;

            player.transform.parent = m_PlayerParent;
            player.name             = name;
            Scoreboard.AddPlayer(player, teamIndex);
            return(player);
        }
        /// <summary>
        /// A new scene was loaded. Spawn the players if the level isn't the main menu.
        /// </summary>
        /// <param name="sceneIndex">The index of the loaded scene.</param>
        public void SceneLoaded(int sceneIndex)
        {
            Application.targetFrameRate = 30;
            // No action for the main menu scene.
            if (sceneIndex == 0)
            {
                enabled = false;
                return;
            }
            timerDisplay = GameObject.Find("Time Limit Text Box").GetComponent <Text>();
            timer        = timeLimit;

            // Find the parent object of all of the players.
            var parentGameObject = GameObject.Find(m_ParentName);

            if (parentGameObject != null)
            {
                m_PlayerParent = parentGameObject.transform;
            }

            // Randomly choose a spawn location. If another character is within the radius of that spawn location then determine a new spawn location.
            var spawnPoints        = DeathmatchSpawnSelection.GetAllSpawnLocations(m_TeamGame, 0);
            var availableLocations = ThirdPersonController.ObjectPool.Get <List <Transform> >();

            availableLocations.Clear();
            for (int i = 0; i < spawnPoints.Length; ++i)
            {
                availableLocations.Add(spawnPoints[i]);
            }

            // Reset the player list.
            Scoreboard.Reinitialize();

            // AI Agents need to know where to take cover.
            m_CoverPoints = GameObject.FindObjectsOfType <CoverPoint>();

            // Add the players to the scoreboard and return early if the component is being forced initialized. The necessary objects should already be instantiated.
            if (m_ForceInitialization)
            {
                m_LocalPlayer = GameObject.FindObjectOfType <ThirdPersonController.Input.UnityInput>().gameObject;
                Scoreboard.AddPlayer(m_LocalPlayer, 0);
                var agents = GameObject.FindObjectsOfType <BehaviorTree>();
                for (int i = 0; i < agents.Length; ++i)
                {
                    Scoreboard.AddPlayer(agents[i].gameObject, i + 1);
                }
                return;
            }

            // Add the local player/camera. Wait to attach the character until after all of the scripts have been created. If in observer mode then only spawn the
            // observer prefab.
            GameObject camera = null;

            if (m_ObserverMode)
            {
                m_LocalPlayer = GameObject.Instantiate(m_ObserverPrefab) as GameObject;
            }
            else
            {
                m_LocalPlayer = InstantiatePlayer(availableLocations, m_PlayerPrefab, m_PlayerName, 0);
                camera        = GameObject.Instantiate(m_CameraPrefab) as GameObject;
            }

            gameManager = GameObject.Find("MultiGame Manager").GetComponent <MultiGameManager>();

            // Spawn the AI agents.
            var startIndex = m_ObserverMode ? 0 : 1; // Start at index 1 in non-observer mode since the player will be on the first team.

            if (m_TeamGame)
            {
                // Create the TeamManager.
                m_TeamManager = gameObject.AddComponent <TeamManager>();

                // The local player should target players on the other team.
                var enemyLayer = 0;
                for (int i = 1; i < m_TeamCount; ++i)
                {
                    enemyLayer |= 1 << LayerMask.NameToLayer(m_Layers[i]);
                }
                if (!m_ObserverMode)
                {
                    // Setup the local player on the first team.
                    SetupPlayer(m_LocalPlayer, 0, 0, LayerMask.NameToLayer(m_Layers[0]), enemyLayer, m_PrimaryTeamColors[0], m_SecondaryTeamColors[0]);
                    TeamManager.AddTeamMember(m_LocalPlayer, 0);

                    // The crosshairs should target the enemy layer.
                    var crosshairsMonitor = GameObject.FindObjectOfType <UI.DeathmatchCrosshairsMonitor>();
                    crosshairsMonitor.CrosshairsTargetLayer = enemyLayer;
                }

                // Setup the team AI agents.
                for (int i = 0; i < m_TeamCount; ++i)
                {
                    // A new set of spawn points need to be returned for any subsequent teams.
                    if (i > 0)
                    {
                        spawnPoints = DeathmatchSpawnSelection.GetAllSpawnLocations(m_TeamGame, i);
                        availableLocations.Clear();
                        for (int j = 0; j < spawnPoints.Length; ++j)
                        {
                            availableLocations.Add(spawnPoints[j]);
                        }
                    }

                    // The AI agent should target players on the other team.
                    var teamLayer = LayerMask.NameToLayer(m_Layers[i]);
                    enemyLayer = 0;
                    for (int j = 0; j < m_TeamCount; ++j)
                    {
                        // Do not allow friendly fire.
                        if (i == j)
                        {
                            continue;
                        }
                        enemyLayer |= 1 << LayerMask.NameToLayer(m_Layers[j]);
                    }

                    // Setup the AI agents.
                    for (int j = startIndex; j < m_PlayersPerTeam; ++j)
                    {
                        var agentNameIndex = m_ObserverMode ? ((i * m_PlayersPerTeam) + j) : ((i * m_PlayersPerTeam) + j - 1);
                        var aiAgent        = InstantiatePlayer(availableLocations, m_AgentPrefab, m_AgentNames[agentNameIndex], i);
                        SetupPlayer(aiAgent, (i * m_PlayersPerTeam) + j, i, teamLayer, enemyLayer, m_PrimaryTeamColors[i], m_SecondaryTeamColors[i]);

                        TeamManager.AddTeamMember(aiAgent, i);
                    }

                    startIndex = 0;
                }
            }
            else
            {
                var playerLayer = LayerMask.NameToLayer(m_Layers[0]);
                if (!m_ObserverMode)
                {
                    // Setup the local player.
                    SetupPlayer(m_LocalPlayer, 0, 0, playerLayer, 1 << playerLayer, m_PrimaryFFAColors[0], m_SecondaryTeamColors[0]);

                    // The crosshairs should target the enemy layer.
                    var crosshairsMonitor = GameObject.FindObjectOfType <UI.DeathmatchCrosshairsMonitor>();
                    crosshairsMonitor.CrosshairsTargetLayer = 1 << playerLayer;
                }
                // Setup the AI agents.
                for (int i = startIndex; i < m_PlayerCount; ++i)
                {
                    var aiAgent = InstantiatePlayer(availableLocations, m_AgentPrefab, m_AgentNames[i - (m_ObserverMode ? 0 : 1)], i);
                    SetupPlayer(aiAgent, i, i, playerLayer, 1 << playerLayer, m_PrimaryFFAColors[i], m_SecondaryFFAColors[i]);
                }
            }

            ThirdPersonController.ObjectPool.Return(availableLocations);
            EventHandler.ExecuteEvent("OnStartGame");
            // The camera will be null in observer mode.
            if (camera != null)
            {
                var cameraController = camera.GetComponent <CameraController>();
                cameraController.Character     = m_LocalPlayer;
                cameraController.DeathAnchor   = Utility.GetComponentForType <Animator>(m_LocalPlayer).GetBoneTransform(HumanBodyBones.Head);
                cameraController.FadeTransform = Utility.GetComponentForType <Animator>(m_LocalPlayer).GetBoneTransform(HumanBodyBones.Chest);
            }
            enabled = true;
        }