I have a few problems here though I think if some are fixed then others will be as well.
I am making an expanding hex based tile game that has no max size. It always starts with a specific tile that I have added to the scene. I also have a gameObject that is a “PossibleTile”. This basically gets replaced on a mouse click with the next actual tile, it is then supposed to add more possible tiles around it if none exist.
I have added the 6 original posible tiles to to the scene and to the list in the inspector. I think one of the problems is that the posible tile isn’t being removed from the surrounding tiles list correctly and is leaving a “missing” entry in the list in the inspector. I get an “ArgumentOutOfRange” error usually when trying to change one of the original tiles after the first one of the original possible tiles. Though it isn’t always related to that.
The second error seems to be a logic or processing error in that not all surrounding tiles are added everytime.
I’m new to the forums sorry if this post is long with the scripts. I added all of the three scripts as the logic errors could appear anywhere. This was still in prototype stage so I would have restructured it later to be more clean and modular.
I have a TileManager Script on a GameManager Object in the scene. This is that script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TileManager : MonoBehaviour {
public Tile[] TileList = new Tile[24]; //Stores every possible tile
public List<Tile> TileDeck; //This is the shuffled deck of the above collection
public Tile CurrentTile; //This is the current tile incase any other code needs quick access to it
public int CurrentTileIndex = 0; //This was anotherway to try to access the Tile in the Deck
public List<Tile> PlacedTiles; //This store all the proper tiles on the map
public List<Tile> SurroundingTiles; //This a list of all possible tile locations
public int ShuffleTimes = 4; //This is the number of times to shuffle the deck
// Use this for initialization
void Start () {
populateDeck(); //Adds all the tiles into the deck
shuffleTileDeck(); //Shuffles the deck
drawTile(); //draws the first tile
}
public void drawTile()
{
CurrentTile = TileDeck[0]; //Draws the top tile of the deck of tiles
}
//This was the old version in case this script was going to place the new tile.
public void placeTile()
{
PlacedTiles.Add(CurrentTile); //Add current Tile to placed tiles
TileDeck.RemoveAt(0); //Remove it from the deck
}
//This function is called from the possible tile when it replaces the tile
public void placeTile(Tile newTile)
{
PlacedTiles.Add(newTile);
TileDeck.RemoveAt(0);
}
//Add actual tiles to a deck of tiles
public void populateDeck()
{
for (int i = 1; i < TileList.Length; i++)
{
TileDeck.Add(TileList[i]);
}
}
//Shuffle Tile Deck
public void shuffleTileDeck()
{
int DeckSize = TileDeck.Count;
for (int i = 0; i < ShuffleTimes; i++)
{
for (int j = 0; j < DeckSize; j++)
{
int k = Random.Range(0, (DeckSize - j));
TileDeck.Add(TileDeck[k]);
TileDeck.RemoveAt(k);
}
}
}
//This was an attempt to remove a possible tile from the list from within this script instead of the possible tile script
public void RemoveTileFromPossibleList(Tile OldTile)
{
SurroundingTiles.Remove(OldTile);
}
//This is a placeholder for later when I need to rotate those tiles.
#region Rotate Tiles
public void RotateTileLeft()
{
CurrentTile.RotationClicks--;
if (CurrentTile.RotationClicks<0)
{
CurrentTile.RotationClicks = 5;
}
}
public void RotateTileRight()
{
CurrentTile.RotationClicks++;
if (CurrentTile.RotationClicks>5)
{
CurrentTile.RotationClicks = 0;
}
}
#endregion
}
Here is the Tile Script:
using UnityEngine;
using System.Collections;
public class Tile : MonoBehaviour{
//Posible edge types
public enum EdgeType
{
Water,
Land,
}
//Each tile has 6 sides and each side is has two sides.
public EdgeType[,] sides = new EdgeType[6,2];
public int Id; //Stores an id for the tile to refer to it in a list
//Simply stores the edges
[Header("Edge Variables")]
[Tooltip("Edge Variables with ship top corner facing left")]
public EdgeType[] TopLeft = new EdgeType[2];
public EdgeType[] Top = new EdgeType[2];
public EdgeType[] TopRight = new EdgeType[2];
public EdgeType[] BottomRight = new EdgeType[2];
public EdgeType[] Bottom = new EdgeType[2];
public EdgeType[] BottomLeft= new EdgeType[2];
//Infor on where the tile is and how many times it rotated from normal.
[Header("Placement Details")]
public int RotationClicks = 0;
public bool Placed = false;
public int GridPos_x;
public int GridPos_y;
//The counter for each type of object on this tile
[Header("Number of Units on Tile")]
public int redUnitCount =0;
public int redShipCount = 0;
public int whiteUnitCount =0;
public int whiteShipCount = 0;
}
Lastly the Possible Tile Script
using UnityEngine;
using System.Collections;
public class PossibleTile : Tile {
//Reference to Tile Manager
public TileManager Tm;
void Start () {
Tm = FindObjectOfType<TileManager>(); //Find TileManager on start
}
void OnMouseDown()
{
//When you click on a posible tile replace it with the curent tile from the tile deck
Tile NewTileSpace = Instantiate(Tm.CurrentTile, transform.position, Quaternion.Euler(90, 0, 0)) as Tile;
NewTileSpace.GridPos_x = GridPos_x;
NewTileSpace.GridPos_y = GridPos_y;
//Call the function from the Tile Manager that adds the new tile to the placed tile list
Tm.placeTile(NewTileSpace);
//Check to see if you can draw a tile
if (Tm.TileDeck.Count != 0)
{
Tm.drawTile(); //Draw a new tile
Tm.SurroundingTiles.Remove(this); //Remove this tile from the surrounding tiles
AddExtraPossibleTiles(NewTileSpace); //Call function to add extra tiles
Destroy(gameObject); //Destroy this possible tile
}
}
public void AddExtraPossibleTiles(Tile NewPlacedTile)
{
//Booleans to check if a tile exists on each side of the possible/newtile
bool TileAboveExists = false;
bool TileBelowExists = false;
bool TileAboveRightExists = false;
bool TileBelowRightExists = false;
bool TileAboveLeftExists = false;
bool TileBelowLeftExists = false;
//Loop though the actual tiles
foreach (Tile Placed in Tm.PlacedTiles)
{
//These tiles share the same x
if (Placed.GridPos_x == NewPlacedTile.GridPos_x)
{
//Check if this tile is 1 higher
if (Placed.GridPos_y == NewPlacedTile.GridPos_y + 1)
{
TileAboveExists = true;
}
//Check if this tile is 1 lower
if (Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileBelowExists = true;
}
}
//Check if the new tile is on an even x coordinate. Odd x coordinates are offset and reversed for some calculations.
if (!IsOdd(NewPlacedTile.GridPos_x))
{
//Check Above Right
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x +1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileAboveRightExists = true;
}
//Check Below Right
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x+1) && Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileBelowRightExists = true;
}
//Check Above Left
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x -1)&& Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileAboveLeftExists = true;
}
//Check Below Left
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileBelowLeftExists = true;
}
}
else //These do the same thing though are offset based off x
{
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y+1)
{
TileAboveRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileBelowRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y+1)
{
TileAboveLeftExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileBelowLeftExists = true;
}
}
}
//Loop through possible tiles to see if they surround the new tile
//This does the same as above but for the possible tiles list
#region Loop Posible Tiles
foreach (Tile Placed in Tm.SurroundingTiles)
{
if (Placed.GridPos_y == NewPlacedTile.GridPos_y + 1)
{
if (!TileAboveExists)
{
if (Placed.GridPos_x == GridPos_x)
{
TileAboveExists = true;
}
}
if (!TileBelowExists)
{
if (Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileAboveExists = true;
}
}
}
if (!IsOdd(NewPlacedTile.GridPos_x))
{
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileAboveRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileBelowRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileAboveLeftExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y - 1)
{
TileBelowLeftExists = true;
}
}
else
{
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y + 1)
{
TileAboveRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x + 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileBelowRightExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y + 1)
{
TileAboveLeftExists = true;
}
if (Placed.GridPos_x == (NewPlacedTile.GridPos_x - 1) && Placed.GridPos_y == NewPlacedTile.GridPos_y)
{
TileBelowLeftExists = true;
}
}
}
#endregion
//Generate a new tile in the spaces where a tile doesn't exist
if (!TileAboveExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3(transform.position.x, transform.position.y, transform.position.z + 173.2051f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = GridPos_x;
NewPTileSpace.GridPos_y = GridPos_y+1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
if (!TileBelowExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3(transform.position.x, transform.position.y, transform.position.z - 173.2051f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = NewPlacedTile.GridPos_x;
NewPTileSpace.GridPos_y = GridPos_y - 1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
if (!TileAboveRightExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3((transform.position.x + 150), transform.position.y, transform.position.z + 86.6f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = GridPos_x+1;
NewPTileSpace.GridPos_y = GridPos_y + 1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
if (!TileBelowRightExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3((transform.position.x + 150), transform.position.y, transform.position.z - 86.6f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = GridPos_x +1;
NewPTileSpace.GridPos_y = GridPos_y - 1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
if (!TileAboveLeftExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3((transform.position.x - 150), transform.position.y, transform.position.z + 86.6f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = GridPos_x-1;
NewPTileSpace.GridPos_y = GridPos_y + 1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
if (!TileBelowLeftExists)
{
Tile NewPTileSpace = Instantiate(this, new Vector3((transform.position.x - 150), transform.position.y, transform.position.z - 86.6f), Quaternion.Euler(90, 0, 0)) as Tile;
NewPTileSpace.GridPos_x = GridPos_x -1;
NewPTileSpace.GridPos_y = GridPos_y - 1;
NewPTileSpace.Id = (Tm.SurroundingTiles.Count + 1);
Tm.SurroundingTiles.Add(NewPTileSpace);
}
}
//Calculate if the x position is odd
public static bool IsOdd(int value)
{
return value % 2 != 0;
}
}