Why I started this project

When dota2’s AutoChess was becoming really popular, I started to play the game myself and I really liked it. I wanted to play the game a lot and get really good at it, but I decided to try to recreate the game instead. I thought that I should be able to create an auto battler type game that wasn’t too complex myself. I did it mostly as a programming challenge.

Creating the board and units

I started building the playing field and the unit ‘bench’. I did this by spawning Node objects in a grid, altering the colors with the adjacent Nodes. The nodes have two properties: The WorldPosition and a boolean that indicates whether they are occupied or not.

To simulate the Units I created a Scriptable Object that holds some of the Unit’s values. For example the unitName, unitCost, unitSprite and the unitShape (which I used to simulate using different models).

Creating the shop

Now that I had created a couple of units, I displayed five random ones to the player. If the player buys one of them, they disappear from the shop and they are placed on the unit ‘bench’.

There is also a reroll button. If the player presses the reroll button, the player loses 5 gold and gets five new purchasable units displayed to them.

Code to move a unit to the first available bench tile

public void PlaceOnBench(GameObject hero)
{
    HeroController heroController = hero.GetComponent<HeroController>();

    //remove from board if the hero was on the board
    if(heroController.OnBoard)
    {
        if (CheckForEntry(boardHeroes, out int oldEntry, hero))
    		boardHeroes[oldEntry] = null;
    }

    //add the hero to the bench at the first empty entry
    if (CheckForEntry(benchHeroes, out int targetIndex, null))
    	benchHeroes[targetIndex] = hero;

    //set the hero position to the tile it has moved to
    if(BenchTiles.Length > 0)
    	hero.transform.position = BenchTiles[targetIndex].spawnPosition;

    //store current tile id
    heroController.OnTile(targetIndex);
}

private bool CheckForEntry(GameObject[] heroArray, out int index, GameObject heroToFind)
{
    for (int i = 0; i < heroArray.Length; i++)
    {
    	if (heroArray[i] == heroToFind)
    	{
        	index = i;
        	return true;
    	}
    }
    index = -1;
    return false;
}

Code to move a unit to different tile

public void MoveHero(GameObject heroToMove, Tile targetTile)
{
	Move moveType = CalculateMoveType(heroToMove, targetTile);
    SetCurrentAndTargetArray(moveType);

    if(ValidSwap(heroToMove, out int oldIndex, out int newIndex))
    	SwapHero(heroToMove, oldIndex, newIndex);

    PlaceHero(heroToMove, targetTile);
}

private bool ValidSwap(GameObject heroToMove, out int oldIndex, out int newIndex)
{
    oldIndex = newIndex = -1;
    //find the heroToMove in the board array
    if (CheckForEntry(currentArray, out oldIndex, heroToMove))
    {
    	//find the heroToMove in the board array
    	if (CheckForEntry(targetArray, out newIndex, null))
    	{
        	return true;
    	}
    }
    return false;
}

private void SwapHero(GameObject heroToMove, int oldIndex, int newIndex)
{
    //remove the hero from the board
    currentArray[oldIndex] = null;
    //add the hero to the bench
    targetArray[newIndex] = heroToMove;
}

private void PlaceHero(GameObject heroToMove, Tile targetTile)
{
    int targetTileIndex;

    HeroController heroController = heroToMove.GetComponent<HeroController>();
    if (targetTile.isBenchTile)
    {
    	targetTileIndex = Array.IndexOf(BenchTiles, targetTile);
    	heroController.OnBoard = false;
    }
    else
    {
    	targetTileIndex = Array.IndexOf(BoardTiles, targetTile);
    	heroController.OnBoard = true;
    }

    //store current tile id
    heroController.OnTile(targetTileIndex);
    //move player to targetTile position
    heroToMove.transform.position = targetTile.spawnPosition;
}