/// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    private bool DetectPlayer()
    {
        // Check if the player is within detection range, and if so, attempt
        // detection.
        if (m_playerDistance < MaxDetectionDistance)
        {
            // Calculate the chance of detection based on the range to
            // the player.
            float playerDetectionChance = LinearTransform(m_playerDistance, 0,
                MaxDetectionDistance, MaxDetectionChance, 0);
            if (Random.value < playerDetectionChance)
            {
                if (m_seeker.IsDone())
                {
                    // If we have detected the player, attempt to get a path.
                    Path path = m_seeker.StartPath(transform.position,
                        Player.transform.position);
                    if (!path.error)
                    {
                        // Reset pathfinding variables.
                        m_lastPathfindingUpdate = 0f;
                        m_currentPath = path;
                        m_currentWaypoint = 0;
                        // Change the change to skeleton state and update animation
                        // variables.
                        m_mode = ZombieMode.Hunting;

                        m_animator.SetFloat("Speed", 1);
                        return true;
                    }
                }
            }
        }
        return false;
    }
    private void UpdatePatrolling()
    {
        WalkSpeed = 25;
        if (DetectPlayer()) return;

        // Test if we have just reached the end of the path.
        if (m_currentWaypoint >= m_currentPath.vectorPath.Count)
        {
            m_currentPath = null;
            m_currentWaypoint = -1;

            m_animator.SetFloat("Speed", 0);
            m_mode = ZombieMode.Idle;
            return;
        }
        else m_animator.SetFloat("Speed", 25);

        if (m_currentWaypoint >= 0 &&
            m_currentWaypoint < m_currentPath.vectorPath.Count - 1) Move();
    }
    private void UpdateHunting()
    {
        WalkSpeed = 50;
        if (m_playerDistance < 2.0)
        {

            m_animator.SetFloat("Speed", 0f);
            m_mode = ZombieMode.Idle;
            return;
        }

        // Check if we have reached the end of the current path.
        if (m_currentPath == null || m_currentWaypoint >= m_currentPath.vectorPath.Count)
        {
            if (m_seeker.IsDone())
            {
                // If so, find a new path to the player.
                Path path = m_seeker.StartPath(transform.position, Player.transform.position);
                if (!path.error)
                {
                    m_lastPathfindingUpdate = 0f;
                    m_lastPlayerPos = Player.transform.position;
                    m_currentPath = path;
                    m_currentWaypoint = 0;
                }
            }
        }

        // If the player has moved significantly since last pathfinding and more
        // than the designated pathfinding interval has passed...
        m_lastPathfindingUpdate += Time.deltaTime;
        if (m_lastPathfindingUpdate > HuntingPathfindingInterval)
        {
            if (m_seeker.IsDone())
            {
                // Re-path to the player and reset pathfinding variables.
                Path path = m_seeker.StartPath(transform.position, Player.transform.position);
                if (!path.error)
                {
                    m_lastPathfindingUpdate = 0f;
                    m_lastPlayerPos = Player.transform.position;
                    m_currentPath = path;
                    m_currentWaypoint = 0;
                }
            }

        }

        if (m_currentWaypoint >= 0 &&
            m_currentWaypoint < m_currentPath.vectorPath.Count - 1) Move();
    }
    private void UpdateIdle()
    {
        if (m_playerDetected)
        {
            WalkSpeed = 0;
            // If within striking range attack the player at random intervals. If
            // not, attempt to get a path to the player and resume hunting.
            if (m_playerDistance < 3f)
            {
                Vector3 displacement = Player.transform.position - transform.position;
                float angle = Vector3.Angle(transform.forward, displacement);

                if (Random.value < 0.05f && Mathf.Abs(angle) < 10)
                {
                    float r = Random.value;
                    if (r < 1)
                    {
                        m_animator.SetBool("Attack", true);
                        m_mode = ZombieMode.Attacking;
                    }
                    return;
                }

                // Reorientate the controller to face towards the player.
                Vector3 direction = Player.transform.position - transform.position;
                direction.Normalize();
                transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 3.5f * Time.deltaTime);
            }
            else
            {
                if (m_seeker.IsDone())
                {
                    Path path = m_seeker.StartPath(transform.position,
                        Player.transform.position);
                    if (!path.error)
                    {
                        // Reset pathfinding variables.
                        m_lastPathfindingUpdate = 0f;
                        m_currentPath = path;
                        m_currentWaypoint = 0;
                        m_mode = ZombieMode.Hunting;
                        m_animator.SetFloat("Speed", 1);

                    }
                }
            }
        }

        else
        {
            m_playerDetected = DetectPlayer();
            if (m_playerDetected) return;

            // Check if the controller should transition from idle to patrolling.
            if (Random.value < PatrolChance)
            {
                if (m_seeker.IsDone())
                {
                    // Get a point within a radius of PatrolRadius units.
                    Vector2 randomPoint = Random.insideUnitCircle * PatrolRadius;
                    Vector3 end = transform.position;
                    end.x += randomPoint.x;
                    end.y = 0.5f;
                    end.z += randomPoint.y;

                    Path path = m_seeker.StartPath(transform.position, end);
                    if (!path.error)
                    {
                        m_lastPathfindingUpdate = 0f;
                        m_currentPath = path;
                        m_currentWaypoint = 0;
                        m_mode = ZombieMode.Patrolling;

                        m_animator.SetFloat("Speed", 0.5f);

                        return;
                    }
                }
            }
        }
    }
    private void UpdateAttacking()
    {
        if (m_attackStart)
        {
            m_attackTime = 0;
            m_attackStart = false;
        }

        m_attackTime += Time.deltaTime;
        if (m_attackTime > 2.76)
        {
            m_attackTime = 0;
            m_attackStart = true;

            m_currentPath = null;
            m_currentWaypoint = -1;
            m_animator.SetBool("Attack", false);
            m_mode = ZombieMode.Idle;
        }
    }
    void Update()
    {
        // Die if health less than 0.
        if (CurrentHealth < 0)
        {
            m_animator.SetBool("Die", true);
            m_mode = ZombieMode.Dead;
            GameObject.Destroy(this.gameObject, 5);
        }

        // Cache distance from the controller to the player.
        m_playerDistance = Vector3.Distance(transform.position,
            Player.transform.position);
        if (m_mode == ZombieMode.Idle)
        {
            UpdateIdle();
        }
        else if (m_mode == ZombieMode.Patrolling)
        {
            UpdatePatrolling();
        }
        else if (m_mode == ZombieMode.Hunting)
        {
            UpdateHunting();
        }
        else if (m_mode == ZombieMode.Attacking)
        {
            UpdateAttacking();
        }
        else if (m_mode == ZombieMode.Dead)
        {

        }
    }
    void SetZeroLegMode()
    {
        _mode = ZombieMode.ZERO_LEGS;

        UpdateParametersByMode();
    }
    void SetOneLegMode()
    {
        _mode = ZombieMode.ONE_LEGS;

        UpdateParametersByMode();
    }
    void SetTwoLegMode()
    {
        _mode = ZombieMode.TWO_LEGS;

        UpdateParametersByMode();
    }