/// <summary>
    /// Move the unit to destination grid position
    /// </summary>
    /// <param name="destination">coords to move to</param>
    /// <returns>true if move successful, false otherwise</returns>
    public bool Move(Coords destination)
    {
        //unhighlight the move tiles when moving
        UnhighlightTiles();

        //create a new Breadth-first search object
        BFS bfs = new BFS();

        //check is unit has no path to destination
        if (!HasPath(destination, ref bfs, moveRange))
        {
            return(false);
        }

        //set new position
        transform.position = Grid.CoordsToWorldSpace(destination);

        return(true);
    }
    /// <summary>
    /// check whether a tile should be highlighted as attackable
    /// </summary>
    /// <param name="tileCoords"></param>
    /// <returns>true if it tile was highlighted, false if it was blocked</returns>
    private bool CheckAndHighlightAttackableTile(Coords tileCoords)
    {
        if (!Grid.InMap(tileCoords))
        {
            return(false);
        }

        bool isFree = _grid.IsFree(tileCoords);

        //highlight if tile is free or if isn't free but has enemy
        if (isFree || _grid.IsEnemy(tileCoords))
        {
            GroundController tile = _mapGenerator.GetTile(tileCoords);
            tile.SetHighlight(GroundController.HighlightType.Attackable);

            //add to highlighted tiles list
            _highlightedTiles.Add(tile);
            return(true);
        }

        return(false);
    }
    public Transform bodyTransform;                                                             //the transform of container of the unit's body & head

    private void Start()
    {
        //get scripts and gameobjects
        _grid         = FindObjectOfType <Grid>();
        _mapGenerator = FindObjectOfType <MapGenerator>();
        _footCircle   = GetComponentInChildren <SpriteRenderer>();
        _animator     = GetComponent <Animator>();

        //get health bar sprite
        Image[] images = GetComponentsInChildren <Image>();
        foreach (var image in images)
        {
            if (image.name == "Health Bar")
            {
                _healthBar = image;
            }
        }

        //unit starts at max health
        _currentHealth = maxHealth;

        //rotate towards down on y axis
        RotateTowards(Direction.Down);
    }
    /// <summary>
    /// Update function when state is select and move
    /// </summary>
    private void SelectAndMoveUpdate()
    {
        //SELECT
        //check if left click was pressed
        if (Input.GetButtonDown("Select"))
        {
            //get collider clicked on
            Collider clickedOnCollider = ClickOnCollider();

            //check if player clicked on collider
            if (clickedOnCollider != null)
            {
                //check if clicked on friendly unit AND unit has action
                if (clickedOnCollider.gameObject.CompareTag("Friendly Unit"))
                {
                    //get unitcontroller clicked on
                    UnitController unitController = clickedOnCollider.gameObject.GetComponent <UnitController>();

                    //check if unit has action or not. If it has no action, don't select anything
                    if (!unitController.GetHasAction())
                    {
                        return;
                    }

                    //select unit clicked on
                    SelectUnit(unitController);
                }
                //clicked on ground
                else
                {
                    //unset selected unit
                    DeselectUnit();
                }
            }
        }

        //MOVE
        //check if right click was pressed and there is a selected unit
        else if (Input.GetButtonDown("Alt Select") && _selectedUnit != null)
        {
            //get collider clicked on
            Collider clickedOnCollider = ClickOnCollider();

            //check if player clicked on collider
            if (clickedOnCollider != null)
            {
                Coords oldCoords = _selectedUnit.GetUnitCoords();                                 //the current coords of selected unit
                Coords toCoords  = Grid.WorldSpaceToCoords(clickedOnCollider.transform.position); //the coordinates player clicked on (to move to)

                //check if grid space clicked is selectedunit's own space. Skip movement in that case
                if (grid.GetGridArray(toCoords) == _selectedUnit.gameObject)
                {
                    _selectedUnit.UnhighlightTiles();
                    SetStateAttacking();
                }

                //check and move unit
                else if (_selectedUnit.Move(toCoords))
                {
                    //move was successful, update grid
                    grid.SetGridArray(toCoords, _selectedUnit.gameObject);
                    grid.SetGridArray(oldCoords, null);

                    //state becomes attacking(with selectedunit)
                    SetStateAttacking();
                }
                else
                {
                    //move failed
                    DeselectUnit();
                }
            }
        }
    }
    /// <summary>
    /// Determine the best move towards attacking range of unit
    /// </summary>
    /// <param name="movingUnitController">the unit that will be moving</param>
    /// <param name="targetUnitController">the unit to move towards</param>
    private void MoveTowardsUnit(UnitController movingUnitController, UnitController targetUnitController)
    {
        Transform movingUnitTransform = movingUnitController.GetComponent <Transform>(); //transform of moving unit
        Coords    movingUnitCoords    = movingUnitController.GetUnitCoords();
        Coords    targetUnitCoords    = targetUnitController.GetUnitCoords();
        int       attackRange         = movingUnitController.GetAttackRange();
        int       moveRange           = movingUnitController.GetMoveRange();

        //Determine best coordinates to move to to be within attack range
        //we will get a couple of coords and then check to see which one is shortest distance from moving unit

        //check the spaces next to target for best space eligibility
        List <Coords> coordsToCheck = new List <Coords>(); //a list of coords to check for best space eligibility

        //look at spaces left of target
        //move from furthest space attackable from to closer to target unit
        for (int x = targetUnitCoords.X - attackRange; x < targetUnitCoords.X; x += 2) //increment by two because if a space isn't good then the next one won't be either
        {
            Coords testCoords = new Coords(x, targetUnitCoords.Y);
            if (targetUnitController.HasDirectPath(testCoords))
            {
                //coords close to target and has direct path, add them to list of coords to check
                coordsToCheck.Add(testCoords);
            }
        }
        //spaces right of target
        for (int x = targetUnitCoords.X + attackRange; x > targetUnitCoords.X; x -= 2)
        {
            Coords testCoords = new Coords(x, targetUnitCoords.Y);
            if (targetUnitController.HasDirectPath(testCoords))
            {
                //coords close to target and has direct path, add them to list of coords to check
                coordsToCheck.Add(testCoords);
            }
        }
        //spaces above target
        for (int y = targetUnitCoords.Y + attackRange; y > targetUnitCoords.Y; y -= 2)
        {
            Coords testCoords = new Coords(targetUnitCoords.X, y);
            if (targetUnitController.HasDirectPath(testCoords))
            {
                //coords close to target and has direct path, add them to list of coords to check
                coordsToCheck.Add(testCoords);
            }
        }
        //spaces below target
        for (int y = targetUnitCoords.Y - attackRange; y < targetUnitCoords.Y; y += 2)
        {
            Coords testCoords = new Coords(targetUnitCoords.X, y);
            if (targetUnitController.HasDirectPath(testCoords))
            {
                //coords close to target and has direct path, add them to list of coords to check
                coordsToCheck.Add(testCoords);
            }
        }

        //evaluate coords that were added to list
        //look for the one with the shortest path from moving unit
        int shortestPathLength = int.MaxValue; //the length of the path to the coords that have the shortest path from moving to target
        BFS shortestPathBFS    = new BFS();    //the bfs of the shortest path to coords

        foreach (var coords in coordsToCheck)
        {
            BFS bfs = new BFS();
            if (movingUnitController.HasPath(coords, ref bfs))
            {
                int solutionLength = bfs.GetSolutionLength();
                if (solutionLength < shortestPathLength)
                {
                    shortestPathLength = solutionLength;
                    shortestPathBFS    = bfs;
                }
            }
        }

        //Move (partially or fully)
        //traverse through bfs
        int    stepsTaken     = 0;                //the number of space moved already
        Coords coordsToMoveTo = movingUnitCoords; //the coords to move to (within moveRange)

        shortestPathBFS.Reset();

        while (stepsTaken < moveRange && shortestPathBFS.HasNext())
        {
            //step along path to destination
            coordsToMoveTo = coordsToMoveTo.Get(shortestPathBFS.Next());

            stepsTaken++; //unit has moved 1 space
        }

        //set new position for moving unit
        movingUnitTransform.position = Grid.CoordsToWorldSpace(coordsToMoveTo);

        //update unit location on grid
        grid.SetGridArray(coordsToMoveTo, movingUnitController.gameObject);
        grid.SetGridArray(movingUnitCoords, null);
    }
 /// <summary>
 /// Get the coordinates of this unit on a grid
 /// </summary>
 /// <returns>the coordinates of this unit</returns>
 public Coords GetUnitCoords()
 {
     return(Grid.WorldSpaceToCoords(transform.position));
 }
 /// <summary>
 /// Check whether coordinates are within attack range of this unit, no direct path necessary
 /// </summary>
 /// <param name="enemyCoords">the enemy coords</param>
 /// <returns>true if within range, false otherwise</returns>
 private bool IsWithinAttackRange(Coords enemyCoords)
 {
     return(Grid.Distance(GetUnitCoords(), enemyCoords) <= attackRange);
 }