private IntVector3 GetFleeLocation()
    {
        // get all available tiles within a radius
        Vector3           worldPointOfInterest = LevelDataManager.Instance.ArrayToWorldSpace(_unit.Navigator.PointOfInterest.x, _unit.Navigator.PointOfInterest.y);
        Vector3           direction            = (_unit.MoveController.Body.position - worldPointOfInterest).normalized; // get opposite direction
        Vector3           worldTargetFleePoint = _unit.MoveController.Body.position + direction * _fleeRadius;
        IntVector3        targetFleePoint      = LevelDataManager.Instance.WorldToArraySpace(worldTargetFleePoint);
        List <IntVector3> availableTiles       = MapService.GetTraversableTiles(
            _fleeRadius, targetFleePoint, _unit, _unit.UnitData.TraversableThreshold, 1);

        if (availableTiles.Count == 0)
        {
            return(_unit.MoveController.MapPosition);
        }
        // iterate thru all the tiles and pick out the best one
        IntVector3 mapPosition     = _unit.MoveController.MapPosition;
        Vector2    currentPosition = _unit.MoveController.Body.position;
        IntVector3 bestTile        = availableTiles[0];
        int        mapDistance     = MapService.DistanceFromStart(mapPosition.x, mapPosition.y, bestTile.x, bestTile.y);
        Unit       currentThreat   = _unit.TargetManager.CurrentTarget;

        for (int i = 0; i < availableTiles.Count; i++)
        {
            // check if initial threat is within sight
            Vector2      targetTilePosition = LevelDataManager.Instance.ArrayToWorldSpace(availableTiles[i].x, availableTiles[i].y);
            float        distanceFromThreat = Vector2.Distance(currentThreat.MoveController.Body.position, targetTilePosition);
            RaycastHit2D hit = Physics2D.Raycast(targetTilePosition, currentThreat.MoveController.Body.position, distanceFromThreat, _unit.TargetManager.VisionLayers);
            if (hit.transform != null)
            {
                // the threat is in sight, skip this tile
                if (hit.transform == currentThreat.MoveController.Body)
                {
                    continue;
                }
            }
            // compare distance
            int newMapDistance = MapService.DistanceFromStart(mapPosition.x, mapPosition.y, availableTiles[i].x, availableTiles[i].y);
            if (newMapDistance > mapDistance)
            {
                bestTile    = availableTiles[i];
                mapDistance = newMapDistance;
            }
        }
        return(bestTile);
    }
    private int GetNearestPatrolPointIndex()
    {
        // get current position
        int        startX                 = _unit.MoveController.MapPosition.x;
        int        startY                 = _unit.MoveController.MapPosition.y;
        int        closestPointIndex      = 0;
        IntVector3 patrolPointMapPosition = LevelDataManager.Instance.WorldToArraySpace(_patrolLoop.PatrolPoints[closestPointIndex].position);
        int        closestDistance        = MapService.DistanceFromStart(startX, startY, patrolPointMapPosition.x, patrolPointMapPosition.y);

        // loop through positions in patrol points
        for (int i = 1; i < _patrolLoop.PatrolPoints.Length; i++)
        {
            patrolPointMapPosition = LevelDataManager.Instance.WorldToArraySpace(_patrolLoop.PatrolPoints[closestPointIndex].position);
            int distance = MapService.DistanceFromStart(startX, startY, patrolPointMapPosition.x, patrolPointMapPosition.y);
            if (distance < closestDistance)
            {
                closestPointIndex = i;
            }
        }
        return(closestPointIndex);
    }