World generator leaving artifacts

I’ve been working on a script that will instantiate a small portion of a much larger world. It should clean up an old row whenever it instantiates a new one but my script has been leaving behind a single tile near the edges and the center when I move in two directions. It seems to happen the worst when I travel South east and never happens when I travel north east. I can’t seem to find the cause of this, any assistance would be greatly appreciated.

using UnityEngine;
using System.Collections;

/// <summary>
/// Instantiate world. 
/// Instantiate world builds the world immediately around the player and keeps it updated.
/// 
/// Accesses LevelGenerator for worldGrid; 
/// </summary>

public class InstantiateWorld : MonoBehaviour 
{	
	//Variables
	
		//The size of the world we want to be instantiated;
		public int worldSize; 
		private int halfWorldSize;
		
	
		//How many tiles off from the center we are.
		private int xOffset;
		private int zOffset;
		
		//The offsets from the last frame. We use this to see if we've moved enough to warrant a new row.
		private int oldxOffset;
		private int oldzOffset;
		
		//The players old position.
		private float oldxPos;
		private float oldzPos;
		
		public GameObject player;  //We'll need to grab the players position to determine where to instantiate the tiles. 
	
		public GameObject landTile; //The object we want to instantiate as the ground.
		public GameObject cliffTile; //The object we want to use for raised ground.
	
		private int tilesize = 10; //The size of the tiles.
	
		public int[,] worldGrid; //The randomly generated world. 
		public GameObject[,] worldTiles; //A list of game objects containing the instantiated world.
		
	
	// Use this for initialization
	

	
	// Update is called once per frame
	void Start () 
	{
		//Figure out which tile the player is on.
		xOffset = (Mathf.RoundToInt(player.transform.position.x/10));
		zOffset = (Mathf.RoundToInt(player.transform.position.z/10));
		oldxOffset = xOffset;
		oldzOffset = zOffset;
		oldxPos = player.transform.position.x;
		oldzPos = player.transform.position.z;
		
		halfWorldSize = Mathf.RoundToInt(worldSize/2);
		
		
		worldGrid = GetComponent<LevelGenerator>().worldGrid;
		worldTiles = new GameObject [worldSize + 1000 , worldSize + 1000];   //Set the array to be filled with the instantiated tiles.
		
		//Instantiate the world
		for(int x = 1; x <= worldSize; x++)
		{
			for(int z = 1; z <= worldSize; z++)
			{
				if(worldGrid.GetLength(0) > x + xOffset  x + xOffset > 0  worldGrid.GetLength(1) > z + zOffset  z + zOffset > 0)
				{
					if(worldGrid[x + xOffset,z + zOffset] == 1)
					{
						worldTiles[x + xOffset - halfWorldSize,z + zOffset - halfWorldSize] = Instantiate(landTile, new Vector3((x + xOffset- (worldSize/2))*tilesize,landTile.transform.position.y,  (z + zOffset- (worldSize/2))*tilesize), landTile.transform.rotation) as GameObject;
					}
					else
					if(worldGrid[x + xOffset,z + zOffset] == 0)
					{
						worldTiles[x + xOffset - halfWorldSize,z + zOffset - halfWorldSize] = Instantiate(cliffTile, new Vector3((x + xOffset- (worldSize/2))*tilesize, cliffTile.transform.position.y , (z + zOffset- (worldSize/2))*tilesize), cliffTile.transform.rotation) as GameObject;
					}
				}
			} 
		} 
	}
	
	void Update()
	{
		
		if(xOffset != oldxOffset || zOffset != oldzOffset)//The player has moved to a new tile.
		{
			//Check if we've moved north.
			if( zOffset > oldzOffset)
			{
				for(int x = 1; x <= worldSize; x++)
				{
					//Check to make sure we're not instantiating outside of the worlds bounds.
					if(worldGrid.GetLength(0) > x + xOffset - halfWorldSize  x + xOffset - halfWorldSize >= 0  worldGrid.GetLength(1) > zOffset + halfWorldSize  zOffset + halfWorldSize > 0)
					{
						if (worldGrid[x + xOffset - halfWorldSize,zOffset + halfWorldSize]  == 1)
						{
							//Instantiate a grass tile.
							worldTiles[x + xOffset - halfWorldSize, zOffset + halfWorldSize] = Instantiate(landTile, new Vector3((x + xOffset- (worldSize/2))*tilesize,landTile.transform.position.y,  (zOffset + (worldSize/2))*tilesize), landTile.transform.rotation) as GameObject;
						}
						else
						if (worldGrid[x + xOffset - halfWorldSize , zOffset + halfWorldSize] == 0)
						{
							//Instantiate a cliff tile.
							worldTiles[x + xOffset - halfWorldSize, zOffset + halfWorldSize] = Instantiate(cliffTile, new Vector3((x + xOffset- (worldSize/2))*tilesize,cliffTile.transform.position.y ,  (zOffset + (worldSize/2))*tilesize), cliffTile.transform.rotation) as GameObject;
						}
					}
					if(worldGrid.GetLength(0) > x + xOffset - halfWorldSize  x + xOffset - halfWorldSize >= 0  worldGrid.GetLength(1) > zOffset - halfWorldSize  zOffset - halfWorldSize >= 0)
					{
						//Destroy the row of tiles we just moved away from.
						Destroy (worldTiles[x + xOffset - halfWorldSize,zOffset - halfWorldSize]);
					}
				}
				//Make sure it doesn't make the same tile more than once.
				oldzOffset = zOffset;
			}
			
			//Check if we've moved south.
			if( zOffset < oldzOffset) 
			{	
				for(int x = 1; x <= worldSize; x++)
				{
					//Check to make sure we're no instantiating outside of the worlds bounds.
					if(worldGrid.GetLength(0) > x + xOffset - halfWorldSize  x + xOffset - halfWorldSize > 0  worldGrid.GetLength(1) > zOffset - halfWorldSize  zOffset - halfWorldSize > 0)
					{
												
						if (worldGrid[x + xOffset - halfWorldSize,zOffset - halfWorldSize]  == 1)
						{
							//Instantiate a grass tile.
							worldTiles[x + xOffset - halfWorldSize,zOffset - halfWorldSize] = Instantiate(landTile, new Vector3((x+xOffset - (worldSize/2))*tilesize,landTile.transform.position.y ,  (oldzOffset - (worldSize/2))*tilesize), landTile.transform.rotation) as GameObject;
						}
						else
						if (worldGrid[x + xOffset - halfWorldSize, zOffset - halfWorldSize] == 0)
						{
							//Instantiate a cliff tile.
							worldTiles[x + xOffset - halfWorldSize,zOffset - halfWorldSize] = Instantiate(cliffTile, new Vector3((x+xOffset - (worldSize/2))*tilesize, cliffTile.transform.position.y ,  (oldzOffset - (worldSize/2))*tilesize), cliffTile.transform.rotation) as GameObject;
						}
					}
					if(worldGrid.GetLength(0) > x + xOffset - halfWorldSize  x + xOffset - halfWorldSize >= 0  worldGrid.GetLength(1) > zOffset + 1 + halfWorldSize  zOffset + 1 + halfWorldSize >= 0)
					{
						//Destroy the row of tiles we just moved away from.
						Destroy (worldTiles[x + xOffset - halfWorldSize, oldzOffset + halfWorldSize]);
					}
				}
				//Make sure it doesn't make the same tile more than once.
				oldzOffset = zOffset;
			}
			
			//Check to see if we've moved east.
			if(xOffset > oldxOffset)
			{
				
				for(int x = 1; x <= worldSize; x++)
				{
					//Check to make sure we're not instantiating outside of the worlds bounds.
					if(worldGrid.GetLength(0) >  xOffset + halfWorldSize  xOffset + halfWorldSize > 0  worldGrid.GetLength(1) > zOffset - halfWorldSize + x  zOffset - halfWorldSize + x > 0)
					{
						if (worldGrid[xOffset+ halfWorldSize,x + zOffset - halfWorldSize] == 1)
						{
							//Instantiate a grass tile.
							worldTiles[xOffset + halfWorldSize, x + zOffset - halfWorldSize] = Instantiate(landTile, new Vector3((xOffset + (worldSize/2))*tilesize,landTile.transform.position.y ,  (x + zOffset -(worldSize/2))*tilesize), landTile.transform.rotation) as GameObject;
						}
						else
						if (worldGrid[xOffset + halfWorldSize,x + zOffset - halfWorldSize] == 0)
						{
							//Instantiate a wall.
							worldTiles[xOffset + halfWorldSize, x + zOffset - halfWorldSize] = Instantiate(cliffTile, new Vector3((xOffset + (worldSize/2))*tilesize,cliffTile.transform.position.y ,  (x + zOffset -(worldSize/2))*tilesize), cliffTile.transform.rotation) as GameObject;
						}
					}
					if(worldGrid.GetLength(0) > xOffset - halfWorldSize  xOffset - halfWorldSize >= 0  worldGrid.GetLength(1) > x + zOffset - halfWorldSize  x + zOffset - halfWorldSize >= 0)
					{
						//Destroy the row of tiles we just moved away from.
						Destroy (worldTiles[xOffset - halfWorldSize, x + zOffset  - halfWorldSize] );
					}
				}
				//Make sure it doesn't make the same tile more than once.
				oldxOffset = xOffset;
			}
			
			 //Check if we've moved west
			if(xOffset < oldxOffset)
			{
				for(int x = 1; x <= worldSize; x++)
				{
					//Check to make sure we're not instantiating outside of the worlds bounds.
					if(worldGrid.GetLength(0) > xOffset - halfWorldSize  xOffset - halfWorldSize > 0  worldGrid.GetLength(1) > x + zOffset - halfWorldSize  x + zOffset - halfWorldSize > 0)
					{
						if (worldGrid[xOffset - halfWorldSize ,x + zOffset - halfWorldSize] == 1)
						{
							//Insantiate a grass tile;
							worldTiles[xOffset - halfWorldSize, x + zOffset - halfWorldSize] = Instantiate(landTile, new Vector3((oldxOffset - (worldSize/2))*tilesize,0,  (x + zOffset -(worldSize/2))*tilesize), landTile.transform.rotation) as GameObject;
						}
						else
						if (worldGrid[xOffset - halfWorldSize,x + zOffset - halfWorldSize] == 0)
						{
							//Instantiate a wall.
							worldTiles[xOffset - halfWorldSize, x + zOffset - halfWorldSize] = Instantiate(cliffTile, new Vector3((oldxOffset - (worldSize/2))*tilesize,cliffTile.transform.position.y ,  (x + zOffset -(worldSize/2))*tilesize), cliffTile.transform.rotation) as GameObject;
						}
					}
					if(worldGrid.GetLength(0) >  xOffset + halfWorldSize  xOffset + halfWorldSize >= 0  worldGrid.GetLength(1) > zOffset - halfWorldSize + x  zOffset - halfWorldSize + x >= 0)
					{
						//Destroy the row of tiles we just moved away from.
						Destroy (worldTiles[oldxOffset + halfWorldSize, x + zOffset - halfWorldSize]);
					}
				}
				//Make sure it doesn't make the same tile more than once.
				oldxOffset = xOffset;
			}
		}
		
		//See if we've moved more than a tilesize in any direction, if so update the offsets.
		if(player.transform.position.x > (oldxPos + tilesize))
		{
			oldxPos = player.transform.position.x;
			xOffset++;
		}
		if(player.transform.position.x < (oldxPos - tilesize))
		{
			oldxPos = player.transform.position.x;
			xOffset--;
		}
		if(player.transform.position.z > (oldzPos + tilesize))
		{
			oldzPos = player.transform.position.z;
			zOffset++;
		}
		if(player.transform.position.z < (oldzPos - tilesize))
		{
			oldzPos = player.transform.position.z;
			zOffset--;
		}
	}
}

Edit: Added in an image to make it easier to understand what it’s leaving behind.
1374585--69456--$World generator leavings.png

I admit I did not run your code, but one thing stood out immediately:

for(int x = 1; x <= worldSize; x++)

Most arrays that I’ve seen start at zero… so you should have your loops run like this:

for(int x = 0; x < worldSize; x++)

Can you try that?

Thanks for your assistance r-dotfunky, I tried what you suggested but unfortunately it’s not it. I set x=1 because it’s used in the placement of the tiles. Thanks again for taking a look at it, I’ve been slamming my head into it all evening.

I hate to bump this but I still can’t seem to find the cause of the bug. Unfortunately this is an integral part of my game.

I can’t test your code without your LevelGenerator class, but on top of what r-dotfunky said I’d try changing:

if(worldGrid.GetLength(0) > xOffset - halfWorldSize  xOffset - halfWorldSize > 0  worldGrid.GetLength(1) > x + zOffset - halfWorldSize  x + zOffset - halfWorldSize > 0)
{
    //Destroy the row of tiles we just moved away from.
    Destroy (worldTiles[xOffset - halfWorldSize, x + zOffset  - halfWorldSize]);
}

to:

if(worldGrid.GetLength(0) > xOffset - halfWorldSize  xOffset - halfWorldSize >= 0  worldGrid.GetLength(1) > x + zOffset - halfWorldSize  x + zOffset - halfWorldSize >= 0)
{
    //Destroy the row of tiles we just moved away from.
    Destroy (worldTiles[xOffset - halfWorldSize, x + zOffset  - halfWorldSize]);
}

(Notice the >= changes in the if condition)

Try making those changes in the few areas that you destroy tiles, and if that doesn’t work consider posting your LevelGenerator class for us to try out too.

Unfortunately >= didn’t seem to fix the problem. The level generator is just a really simple placeholder that fills the array with 1’s and lines the outside with 0’s. You’ll want to plug in a flat tile for the grass. I’ll keep poking at it here, thank you for your time and assistance!

using UnityEngine;
using System.Collections;

/// <summary>
/// Generates the world and places it in worldGrid.
/// 
/// 
/// 0 is a cliff
/// 1 is grass
/// 
/// </summary>
/// 
public class LevelGenerator : MonoBehaviour 
{
	//Variables
	
		//The tile size of the world.
		public int worldWidth;  //X axis
		public int worldLength; //Z axis
	
		public GameObject landTile; //The object we want to instantiate as the ground.
		public GameObject cliffTile; //The object we want to use for raised ground.
	
		//The world being stored. Should give me each tile type.
		public int[,] worldGrid;
		
	
	
	// Use this for initialization
	void Start () 
	{
		worldGrid = new int [worldWidth + 1 ,worldLength + 1]; 
		
		//Run along the grid marking everything as ground.
		for(int x = 1; x <= worldWidth; x++)
		{
			for(int z = 1; z <= worldLength; z++)
			{
				//If it's the first or last in it's row make it a cliff to lock the player inside.
				if(x != 1  x != worldWidth  z != 1  z != worldLength)
				{
					worldGrid[x,z] = 1;
				}
				else
				{
					worldGrid[x,z] = 0;
				}
			}
		}
	}
}

Another bump. There was some delay, I had to pause working on the script for school but I’m back and ready to continue to search for an answer.

If you start at x= 1 you would end at Max + 1?

If that doesn’t work just drop some homing missile and let them remove the extra pieces lol.

The artifacts only appear when the player moves in two of the cardinal directions, they don’t have to be at the same time just so long as he’s altering between them. The rest of the time it works fine so I’m fairly confidant it’s not with my x=1, I did however increase the max by one with x <=.