private bool DoWeNeedToWaitForTooCloseSpider(GameObject otherSpider)
    {
        WalkStage otherWalkStage = closestSpiderController.currentWalkStage;

        return(otherWalkStage == WalkStage.Avoid || otherWalkStage == WalkStage.Turn ||
               (otherWalkStage == WalkStage.Wait && DoesThisSpiderHavePriority(spiderWeAreWaitingFor)));
    }
    private void SetWalkStage(WalkStage newWalkStage)
    {
        if (currentWalkStage != newWalkStage)
        {
            currentWalkStage = newWalkStage;

            if (newWalkStage == WalkStage.Wait)
            {
                timeToLeaveWait = -1;
                SetIdleAnim();
            }
            else
            {
                SetWalkAnim(spiderSpecificConstants.BASE_WALK_SPEED * walkMultiplier);
            }
        }
    }
    private void HandleWalkStage()
    {
        float borderProgress = GetBorderProgressAmount();

        //We have to do this first as we'll be checking if we're in the turn stage in the next block
        if (borderProgress != -1 && currentWalkStage != WalkStage.Wait)
        {
            SetWalkStage(WalkStage.Turn);
        }
        else
        {
            SetBorderPriority(BorderPriorities.None);
        }

        //If there's a spider too close to us
        if (null != closestSpider)
        {
            switch (currentWalkStage)
            {
            case WalkStage.Forward:
                SetWalkStage(WalkStage.Avoid);
                spiderBeingAvoided = closestSpider;
                break;

            case WalkStage.Turn:
                if (closestSpiderController.currentWalkStage == WalkStage.Turn && DoesThisSpiderHavePriority(closestSpider))
                {
                    spiderWeAreWaitingFor = closestSpider;
                    SetWalkStage(WalkStage.Wait);
                }
                else if (borderProgress == -1)
                {
                    SetWalkStage(WalkStage.Forward);
                }
                break;

            case WalkStage.Avoid:
                if (spiderBeingAvoided != closestSpider && closestSpiderController.currentWalkStage == WalkStage.Turn)
                {
                    spiderWeAreWaitingFor = closestSpider;
                    SetWalkStage(WalkStage.Wait);
                }
                //If the spider is avoiding another spider that isn't us, the one with lower priority waits
                else if (closestSpiderController.currentWalkStage == WalkStage.Avoid &&
                         closestSpiderController.spiderBeingAvoided != gameObject && DoesThisSpiderHavePriority(closestSpider))
                {
                    spiderWeAreWaitingFor = closestSpider;
                    SetWalkStage(WalkStage.Wait);
                }
                break;

            case WalkStage.Wait:

                WalkStage otherWalkStage = closestSpiderController.currentWalkStage;
                if (closestSpider != spiderWeAreWaitingFor && DoWeNeedToWaitForTooCloseSpider(closestSpider))
                {
                    //Then we should wait for this new spider instead
                    timeToLeaveWait       = -1;
                    spiderWeAreWaitingFor = closestSpider;
                }
                break;
            }
        }
        else if (borderProgress == -1 && timeToLeaveWait == -1)
        {
            //If there are no spiders too close, we're not at the border, and not preparing to leave wait, we can walk forward normally
            SetWalkStage(WalkStage.Forward);
            spiderBeingAvoided = null;
        }

        switch (currentWalkStage)
        {
        case WalkStage.Forward:
            if (walkStageElapsedTime < walkStageDuration)
            {
                transform.position   += transform.forward * Time.deltaTime * randomWalkSpeed;
                walkStageElapsedTime += Time.deltaTime;
            }
            else
            {
                SetWalkStage(WalkStage.None);
                NextMovementStage();
            }
            break;

        case WalkStage.Turn:
            Vector3 tableDirection = tableCentrePosition - transform.position;

            float rotateSpeed = spiderSpecificConstants.BASE_BORDER_TURN_SPEED;
            if (walkMultiplier > 1)
            {
                rotateSpeed = rotateSpeed * walkMultiplier;
            }

            if (null != closestSpider && closestSpiderDistance < GetMaxSpiderAvoidDistanceWithScaleMult())
            {
                rotateSpeed = rotateSpeed * (GetMaxSpiderAvoidDistanceWithScaleMult() - closestSpiderDistance) / (GetMaxSpiderAvoidDistanceWithScaleMult() - GetMinSpiderAvoidDistanceWithScaleMult());
            }
            else
            {
                rotateSpeed = rotateSpeed * borderProgress;
            }

            TurnToTargetDirection(GetBorderTurnDirection(), walkMultiplier);
            transform.position += transform.forward * Time.deltaTime * randomWalkSpeed;

            if (debugEnabled)
            {
                Color debugColorGreen   = new Color(0, 1, 0, Mathf.Clamp01(borderProgress));
                Color debugColorMagenta = new Color(1, 0, 1, Mathf.Clamp01(borderProgress));
                Debug.DrawRay(transform.position + debugOffset, transform.forward * DEBUG_RAY_LENGTH_MULTIPLIER, debugColorGreen);
                Debug.DrawRay(transform.position + debugOffset, tableDirection, debugColorMagenta);
            }

            break;

        case WalkStage.Avoid:
            float turnSpeedMultiplier;

            if (spiderToAvoidIsInSector)
            {
                turnSpeedMultiplier = (spiderSpecificConstants.SPIDER_AVOIDANCE_SECTOR_MAX_ANGLE - closestSpiderAngle) / (spiderSpecificConstants.SPIDER_AVOIDANCE_SECTOR_MAX_ANGLE - spiderSpecificConstants.SPIDER_AVOIDANCE_SECTOR_MIN_ANGLE);
            }
            else
            {
                turnSpeedMultiplier = (GetMaxSpiderAvoidDistanceWithScaleMult() - closestSpiderDistance) / (GetMaxSpiderAvoidDistanceWithScaleMult() - GetMinSpiderAvoidDistanceWithScaleMult());
            }

            float turnSpeed = spiderSpecificConstants.BASE_AVOID_TURN_SPEED * walkMultiplier * turnSpeedMultiplier;

            TurnToTargetDirection(transform.position - closestSpider.transform.position, walkMultiplier * turnSpeedMultiplier);
            transform.position += transform.forward * Time.deltaTime * randomWalkSpeed;

            if (debugEnabled)
            {
                Color debugColorGreen = new Color(0, 1, 0, Mathf.Clamp01(turnSpeedMultiplier));
                Color debugColorRed   = new Color(1, 0, 0, Mathf.Clamp01(turnSpeedMultiplier));
                Debug.DrawRay(transform.position + debugOffset, transform.forward * DEBUG_RAY_LENGTH_MULTIPLIER, debugColorGreen);
                Debug.DrawRay(transform.position + debugOffset, (transform.position - closestSpider.transform.position) * DEBUG_RAY_LENGTH_AVOID_MULTIPLIER, debugColorRed);
            }
            break;

        case WalkStage.Wait:

            WalkStage otherWalkStage = closestSpiderController.currentWalkStage;

            //If we haven't stopped waiting, and the spider isn't too close, or it is but we don't need to wait for it anyway
            if (timeToLeaveWait == -1 &&
                (!IsSpiderTooClose(spiderWeAreWaitingFor) || !DoWeNeedToWaitForTooCloseSpider(spiderWeAreWaitingFor)))
            {
                timeToLeaveWait = Time.time + ADDITIONAL_WAIT_TIME;
            }

            if (debugEnabled)
            {
                float opacityMultiplier;
                if (timeToLeaveWait == -1)
                {
                    opacityMultiplier = 1;
                }
                else         //1 if we've just started waiting
                {
                    opacityMultiplier = (timeToLeaveWait - Time.time) / ADDITIONAL_WAIT_TIME;
                }

                Color debugColorYellow = new Color(1, 0.92f, 0.016f, opacityMultiplier);
                Debug.DrawLine(transform.position + debugOffset, spiderWeAreWaitingFor.transform.position + debugOffset, debugColorYellow);
            }
            break;
        }
    }