Tile worldbuilder script gives bugs; plz take a look :)

Hello again,

Im working on a chase game. For this id like to use a neverending world which spawns in basic obstables and powerups. Ive tried to write my own tilebased worldbuilder script with reasonable succes untill now. Id really appreciate any help cause it feels like my brain has turned into slush. I cant even think out any other/better approach to this. I got some advice on Mirc but it was over my head; cant really figure out how to approach this better.

Before pasting the code ill explain the basic principle.

The world is generated dynamically. The vars at the top dictate dimensions of the world. gridSize is the size of the “cells” (and therefore also dicates the size of the tiles) and worldSize is the amount of tiles the world is wide and deep. tileOffset is just a derivative value of the worldSize which helps me read my own code. newWorld is the array that will hold the tiles.

Under start i create a 2dimensional array the size of worldsize. I then fill this array with tiles. The yield WaitForSeconds() is just so i could see how it was being build.

Under update i compare the distance that the player has to the centerpoint of the tileworld. The script is attached to a gameobject which steps towards the center of the next tile the player walks on. So whenever the distance over one axis becomes greater then the positive or negative value of half the gridsize i offset the tileworld gameobject a full gridsize in that axis.

Offcourse thats not the only thing that happens which is what OffsetZ() and OffsetX() are for.

What happens when the player moves into another gridcell is the following:

  • The gameobject tileworld is moved into that next cell
  • depending on the direction the array is being run through column by column or row by row (for z row by row and for x column by column from my head)
  • the tiles at the “back” (depending on direction) of the row/column will be destroyed (including “child” objects like the apples)
  • the remaining values on that column/array will be shifted towards that empty spot essentially creating a new “empty” spot at the front of that row/column
  • a new tile will be spawned in that empty spot and at the relevant position in comparison to the tileworld gameobject which we know is in the center of the tileworld (since we just moved it there)
  • this gets repeated over the other dimension in the array (so it happens throughout the entire array not just for one strip of tiles)

I hope this was not too boring for you guys but i wouldnt feel ok just dumping this in here without an explanation of my intentions while asking for help.

Here is the script:

var playerPos : Transform; 
var tilePrefab : GameObject; //simple flattened cube 10 units square
var gridSize = 10; //tileprefab has to be this size!
var worldSize = 5; //size of the world in tiles, always an uneven number

private var tileOffset = (worldSize - 1) / 2; //this just makes the code more readable
private var worldOffsetZ : float; //offset from the worldcenter (center tile)
private var worldOffsetX : float; //offset from the worldcenter (center tile)

var newWorld = null; //newWorld is globally defined so i can change the array from Update() while i build it in Start()

function OffsetZ(){

		if (worldOffsetZ > 0){	
		transform.position.z += gridSize;  //make the center of the "world" that this script is on jump one gridsize
			for (i =- tileOffset; i <= tileOffset; i ++){ //make the counter equal to index of the size of the array/world
			newWorld[0][i + tileOffset].GetComponent(DestroySelf).DestroySelf(); //destroy all tiles on column 0 of the array
				for (j =- tileOffset; j <= tileOffset - 1; j ++){ //shift all values but dont touch the last column
					newWorld[j + tileOffset][i + tileOffset] = newWorld[j + tileOffset + 1][i + tileOffset];
				}
		newWorld[worldSize - 1][i + tileOffset] = Instantiate(tilePrefab, transform.position + Vector3(gridSize * i, 0, tileOffset * gridSize), Quaternion.identity);  //create new tile
		}
	}
	
		else{	
		transform.position.z -= gridSize;  //make the center of the "world" that this script is on jump one gridsize
			for (i =- tileOffset; i <= tileOffset; i ++){ //make the counter equal to index of the size of the array/world
			newWorld[worldSize - 1][i + tileOffset].GetComponent(DestroySelf).DestroySelf(); //destroy all tiles on column 0 of the array
				for (j = tileOffset; j >= -tileOffset + 1; j --){ //counting backwards and staying away from the first column
					newWorld[j + tileOffset][i + tileOffset] = newWorld[j + tileOffset - 1][i + tileOffset];
				}
		newWorld[0][i + tileOffset] = Instantiate(tilePrefab, transform.position + Vector3(-gridSize * i, 0, tileOffset * -gridSize), Quaternion.identity);  //create new tile
		}
	}
}

function OffsetX(){

if (worldOffsetX > 0){	
		transform.position.x += gridSize;
			for (i =- tileOffset; i <= tileOffset; i ++){ //make the counter equal to index of the size of the array/world
			newWorld[i + tileOffset][0].GetComponent(DestroySelf).DestroySelf(); //destroy all tiles on row 0 of the array
				for (j =- tileOffset; j <= tileOffset - 1; j ++){
					newWorld[i + tileOffset][j + tileOffset] = newWorld[i + tileOffset][j + tileOffset + 1];
				}
		newWorld[i + tileOffset][worldSize - 1] = Instantiate(tilePrefab, transform.position + Vector3(tileOffset * gridSize, 0, gridSize * i), Quaternion.identity);
		}
	}
	
		else{	
		transform.position.x -= gridSize;
			for (i =- tileOffset; i <= tileOffset; i ++){ //make the counter equal to index of the size of the array/world
			newWorld[i + tileOffset][worldSize - 1].GetComponent(DestroySelf).DestroySelf(); //destroy all tiles on row 0 of the array
				for (j = tileOffset; j >= -tileOffset + 1; j --){
					newWorld[i + tileOffset][j + tileOffset] = newWorld[i + tileOffset][j + tileOffset - 1];
				}
		newWorld[i + tileOffset][0] = Instantiate(tilePrefab, transform.position + Vector3(tileOffset * -gridSize, 0, -gridSize * i), Quaternion.identity);
		}
	}
}


function Start (){

newWorld = new Array(worldSize);  //build the initial array to hold the world
	for (i = 0; i < worldSize; i ++){
	newWorld[i] = new Array(worldSize); //create subarrays to make it 2dimensional
	}
	
for (i =- tileOffset; i <= tileOffset; i ++){ //fill the array with the basetiles the player starts on
	for (j =- tileOffset; j <= tileOffset; j ++){
		newWorld [i + tileOffset] [j + tileOffset] = Instantiate(tilePrefab, transform.position + Vector3(gridSize * j, 0, gridSize * i), transform.rotation);
		yield WaitForSeconds (0.05); //just to see how the world gets build
		}
	}

}

function Update(){

worldOffsetZ = playerPos.position.z - transform.position.z; //calculate offset from the current world origin
worldOffsetX = playerPos.position.x - transform.position.x;

if(worldOffsetZ >= gridSize * 0.5 || worldOffsetZ <= -gridSize * 0.5){ //call in worldoffsetZ if player enters next cell based on gridSize
OffsetZ();
}

if (worldOffsetX >= gridSize * 0.5 || worldOffsetX <= -gridSize * 0.5){ //call in worldoffsetZ if player enters next cell based on gridSize
OffsetX();
}

}

Now i realize this is very much written out. I had this optimized with a seperate ArrayShift routine (which works on its own) but since i got bugs with this i decided to write it all to see if it would help me spot my mistake.


What happens when i run is this. Whenever i only check for one axis it works absolutely flawless. It runs forever, its fast and with a huge worldsize it stretches to the horizon without problems. It goes bad when i enable both axis. The tiles start to seperate diagonally when the player moves diagonally as well. Ive tried lots of things like checking if the OffsetX and OffsetY were running at the same time with Debug.Log on each function but i never got proof they were running at the same time. (i.e. both shifting array values at the same time) although this is what it looks like when i test it.

The webbuild (with this problem) is here:
http://members.casema.nl/jw.v.dronkelaar/angrytornado/angrytornado.html

W - Build up speed
S - Deccelerate
A - Turn left
D - Turn right

Apples boost your speed

I would really love to get some help on this. While this script may seem small to you guys it represents a huge amount of my time and i feel im close to having it work. Im just missing something obvious.

Im open to all suggestions including better approaches. Anything that will get me “unstuck” at this point would be much appreciated. :slight_smile:

3dioot

Im normally not one to bump but it would be great if i could get some advice on this. :sweat_smile:

The weekend is coming up and i look forward to continue building on my game but i really need the world to function at a somewhat acceptable level before i cant start implementing the rest of the features.

Again, any input, including how to approach it in a different/better way is appreciated. :slight_smile:

3dioot

Let me just rebump this and at the same time say…

Usually when there is a lot of code, there are only a few people that will try and help because it takes so long. I would help but I can’t script really well yet.

Well, thanks for caring anyway. :wink:

For now ill focus on some simpler stuff and some asset creation. Little sense for me to keep staring at that same block of code. :lol:

Cheers

3dioot

Indeed. Good luck.