public void DisplayReachableTilesForCurrentUnit()
    {
        DestroyReachableTilesDisplayHelp();

        if (currentlySelectedUnit != -1)
        {
            var currentUnit    = playerUnits[currentlySelectedUnit];
            var reachableTiles = TilemapHelper.FindReachableTiles(currentUnit.TilePosition, currentUnit.ActionPoints, tilemap);
            foreach (var fringe in reachableTiles)
            {
                foreach (var tile in fringe)
                {
                    if (tile.Item2 <= currentUnit.ActionPoints)
                    {
                        var newHelper = Instantiate(Resources.Load("RangeHexagon"), RangeDisplayHelper.transform) as GameObject;
                        var cellPos   = tilemap.CellToWorld(tile.Item1);
                        newHelper.transform.position = new Vector3(cellPos.x, newHelper.transform.position.y, cellPos.z);
                    }
                }
            }
        }
    }
    public void Update()
    {
        playerUnits.RemoveAll(item => item == null); // remove destroyed units
        if (playerUnits.Count == 0)
        {
            currentlySelectedUnit = -1;
        }

        if (!calledRangeDisplayHelperOnce)
        {
            DisplayReachableTilesForCurrentUnit();
            calledRangeDisplayHelperOnce = true;
        }

        // Change unit selection
        if (Input.GetMouseButtonDown(0))
        {
            var clickedCell     = GetTileClick();
            var unitsOnThatCell = playerUnits.Where(unit => unit.TilePosition == clickedCell && unit.ActionPoints > 0).ToList();
            if (unitsOnThatCell.Count > 0)
            {
                currentlySelectedUnit = playerUnits.IndexOf(unitsOnThatCell.First());

                var currentUnit = playerUnits.Find(a => a == unitsOnThatCell.First());

                DisplayReachableTilesForCurrentUnit();

                Debug.Log("Changed selection to " + currentUnit.name + ", " + currentUnit.ActionPoints + " AP left");
                audioController.PlayUnitChooseSound();
            }
        }
        // Movement
        else if (Input.GetMouseButtonDown(1))
        {
            if (playerUnits.Count > 0)
            {
                var clickedCell        = GetTileClick();
                var clickedTile        = (AbstractGameTile)tilemap.GetTile(clickedCell);
                var currentUnit        = playerUnits[currentlySelectedUnit];
                var reachableTiles     = TilemapHelper.FindReachableTiles(currentUnit.TilePosition, currentUnit.ActionPoints, tilemap);
                var reachableFireTiles = TilemapHelper.FindReachableFireTiles(currentUnit.TilePosition, currentUnit.ActionPoints, tilemap);

                int cellInFringe     = -1;
                int fireCellInFringe = -1;
                Tuple <Vector3Int, int> targetTile     = null;
                Tuple <Vector3Int, int> targetFireTile = null;
                for (int fringe = 0; fringe < reachableTiles.Count; fringe++)
                {
                    var reachableTile = reachableTiles[fringe].Where(tile => tile.Item1 == clickedCell).ToList();
                    if (reachableTile.Count > 0)
                    {
                        targetTile   = reachableTile.First();
                        cellInFringe = fringe;
                        break;
                    }
                }
                for (int fringe = 0; fringe < reachableFireTiles.Count; fringe++)
                {
                    var reachableFireTile = reachableFireTiles[fringe].Where(tile => tile.Item1 == clickedCell).ToList();
                    if (reachableFireTile.Count > 0)
                    {
                        targetFireTile   = reachableFireTile.First();
                        fireCellInFringe = fringe;
                        break;
                    }
                }

                if (cellInFringe >= 0 && !playerUnits.Any(unit => unit.TilePosition == clickedCell) && (currentUnit.ActionPoints >= targetTile?.Item2 || currentUnit.ActionPoints >= targetFireTile?.Item2))
                {
                    Debug.Log("Moved unit " + currentUnit.name + " from " + currentUnit.TilePosition + " to " + clickedCell + ", costing " + targetTile.Item2 + ". There are " + (currentUnit.ActionPoints - targetTile.Item2) + " AP left.");
                    currentUnit.ActionPoints            -= targetTile.Item2;
                    currentUnit.TilePosition             = clickedCell;
                    currentUnit.ObjectTransform.position = new Vector3(tilemap.CellToWorld(clickedCell).x, 0, tilemap.CellToWorld(clickedCell).z);

                    audioController.PlayUnitMoveSound();

                    DisplayReachableTilesForCurrentUnit();

                    // Select next unit, no AP remaining
                    ChooseNextUnitOrGoToNextRound();
                }
            }
        }
        else if (Input.GetKeyDown(KeyCode.E))
        {
            ExecuteAction(playerUnits[currentlySelectedUnit].UnitActions[0], playerUnits[currentlySelectedUnit].UnitType, playerUnits[currentlySelectedUnit]);
        }
        // Skip to next turn
        else if (Input.GetKeyDown("space"))
        {
            //currentlySelectedUnit = 0;
            UpdateTiles();
        }

        if (currentlySelectedUnit != -1)
        {
            UnitSelector.transform.position = playerUnits[currentlySelectedUnit].transform.position;
        }
        else
        {
            Destroy(UnitSelector);
        }
    }
    private IEnumerator SpreadFire(Dictionary <System.Type, List <Vector3Int> > tiles, bool dynamicSpread)
    {
        // find fire epicenter
        var fireTiles = TilemapHelper.GetTileDictionary(tilemap)[typeof(FireTile)];

        if (fireTiles.Count > 0)
        {
            var average = fireTiles.Aggregate((acc, cur) => acc + cur) / fireTiles.Count;

            StartCoroutine(LerpCameraTo(mainCamera.transform.position, new Vector3(tilemap.CellToWorld(average).x, mainCamera.transform.position.y, tilemap.CellToWorld(average).z - 5f), 0.5f, 0.5f));
            yield return(new WaitForSecondsRealtime(1f));
        }

        var newTilesOnFireCnt = 0;

        foreach (var fireTile in tiles[typeof(FireTile)])
        {
            var currentFireTile = (AbstractGameTile)tilemap.GetTile(fireTile);
            currentFireTile.TileProperties.RoundsOnFire++;
            if (currentFireTile.TileProperties.RoundsOnFire >= 1)
            {
                tilemap.SetTile(fireTile, Resources.Load("BurntTile", typeof(BurntTile)) as BurntTile);
            }

            if (dynamicSpread)
            {
                var reachableNeighbors = TilemapHelper.FindReachableTiles(fireTile, 1, tilemap);
                if (reachableNeighbors.Count >= 2)
                {
                    var possibleTilesToSpreadTo = reachableNeighbors[1];
                    var spreadToThisManyTiles   = (int)Math.Ceiling(possibleTilesToSpreadTo.Count * 0.66f);
                    //var spreadToThisManyTiles = (possibleTilesToSpreadTo.Count - 1) / 2 + 1; // divide by two, but round up
                    var spreadTo = possibleTilesToSpreadTo.OrderBy(x => random.Next()).Take(spreadToThisManyTiles); // randomly choose elements from list
                    foreach (var tile in spreadTo)
                    {
                        var actualTile = (AbstractGameTile)tilemap.GetTile(tile.Item1);
                        if (actualTile.TileProperties.IsFlammable)
                        {
                            tilemap.SetTile(tile.Item1, Resources.Load("FireTile", typeof(FireTile)) as FireTile);
                            newTilesOnFireCnt++;
                        }
                    }
                }
            }
            else
            {
                var neighbors = TilemapHelper.FindNeighbors(fireTile, tilemap);
                foreach (var neighborType in neighbors.Keys)
                {
                    foreach (var neighbor in neighbors[neighborType])
                    {
                        var tile = (AbstractGameTile)tilemap.GetTile(neighbor);
                        if (tile.TileProperties.IsFlammable)
                        {
                            tilemap.SetTile(neighbor, Resources.Load("FireTile", typeof(FireTile)) as FireTile);
                            // replace goal tile with burntGoalTile
                            newTilesOnFireCnt++;
                        }
                    }
                }
            }
        }

        if (newTilesOnFireCnt == 0)
        {
            levelIsComplete = true;
            Debug.Log("Level complete, no fire can spread anymore");
            audioController.PlayMissionSuccessSound();

            StartCoroutine(StartNextLevelDelayed(3));
        }
        else
        {
            audioController.PlayFireSpreadSound();
        }

        if (currentlySelectedUnit != -1)
        {
            StartCoroutine(LerpCameraTo(mainCamera.transform.position, new Vector3(playerUnits[currentlySelectedUnit].transform.position.x, mainCamera.transform.position.y, playerUnits[currentlySelectedUnit].transform.position.z - 5f), 0.5f, 0.5f));
            yield return(new WaitForSecondsRealtime(1f));
        }

        DisplayReachableTilesForCurrentUnit();
        CreateRandomTileProps();
    }