Collumns Match 3 remake - Help with matchmaking and neighbor gems of same type.

Hello all,
I am writing a columns (SEGA) match 3 remake type game. I’ve adopted several methods for my design on setting up my grid (2D Array), spawning gems, moving and collision withOUT colliders. This is my 1st project in Unity and I am not a pro at coding yet :slight_smile: but for the life of me, I am having the WORST time trying to get the match making system to work . I have read about 900 hours of posts (laugh, I know you’ve been there) and I understand the pseudo version of what I want to do, I just can’t seem to get the code working. I’ve included my code snips of what I have done thus far, would anyone be able to assist me with completion of this stage in my efforts? I am (at this point) checking the MATERIAL of the incoming gem against the MATERIAL of the “bottom” gem of my dropping 3 gem stack.
I want to take all the matches in the end and put them in a list so I can do the removal of gems and the shifting downward of falling gems easier. I was also trying to use a list as a “collector” of gems so I could use that to find all eight neighbors…alas, that part is not working.

Thanks
King


UPDATE:

UPDATE:

Ive managed to get match making working, kind of… It seems to match up and down incorrectly sometimes and wont destroy or move blocks down.At the moment im not destroying diag matches, but it does seem to check for the diag matches of 3 or more. I’ve included my updated code. I am not sure if I am even approaching this in the correct manner. Can anyone take a look at the code and tell me what may be wrong with the match making and the “Restacking” of the “pile” when gems get removed? I am storing a temp list of POSSIBLE matches, checking up and down, storing all found matches in the temp list, checking left and right, then adding everything together from my temp list to a “master” list of what gems to destroy. i’ve been at this for about 15 days and am stumped. I posted my question here about match making, got 31 views (at this point) and NO answers or suggestions. I would have at least figured that Eric5h5 would have chimed in based on some of his tutorials ive read? :slight_smile:
I used the Unity Plus Tutorial Tetris game tutorial - part 1 and 2 as a basis for my movement and 2d grid board.
A little help please? :slight_smile:

Thanks
King


//Check each gem for matching material (or whatever compare we decide)	
void CheckGem(GameObject gem)
	{
		if(matchingMaterial != null)
		{
			//if the color of the current gem matches the matching color
			if(gem.renderer.sharedMaterial == matchingMaterial)
				{
				isGemMatching = true;
				//Add the gem to the list of gems to remove.
				collectorOfPossibleMatches.Add (gem);
				
Debug.Log ("*** The GEMS MATCH! *** matchingMaterial:  "+matchingMaterial);
Debug.Log ("gem.renderer.sharedMaterial: "+gem.renderer.sharedMaterial);
Debug.Log("ADD the Gem to our list - colloctorOfPossibleMatches: "+collectorOfPossibleMatches.Count);
				}
			else if(gem.renderer.sharedMaterial != matchingMaterial)
			{
				isGemMatching = false;
print ("----------- GEM DOES NOT MATCH -----------");
			
			}
			
		}
		else
		//if the color we are matching to doesnt exist (its the original gem), then assign gem color to it
		{ 
		matchingMaterial = gem.renderer.sharedMaterial;
Debug.Log ("IF on FIRST PASS there is NO material to MATCH matchingMaterial to then add current bottom gem: "+matchingMaterial);
		CheckGem (gem); // changed the material, go check again.
		}
	}

//Check for a match
void CheckForMatch(GameObject startObject)
	{
		collectorOfPossibleMatches.Clear();
		matchingListOfGemsToRemove.Clear();
		collectorOfPossibleMatches.Add (startObject);
		matchingListOfGemsToRemove.Add (startObject);
		
Debug.Log ("collector.COUNT: "+collectorOfPossibleMatches.Count);		
		matchingMaterial = startObject.renderer.sharedMaterial;
	
		CheckNeighbors(startObject);
		
		//Make sure we have SOMETHING in our final list of gems to remove
		if(matchingListOfGemsToRemove.Count >= minNumOfGemsToCauseMatch)
		{
		//There is enough gems in the list to destroy/clear/move
		DestroyMatchingGems();
		//Clear our temp list of storage of possible matches as we are done with it.
		collectorOfPossibleMatches.Clear();
		matchingListOfGemsToRemove.Clear();
		}
		
print("leftCount:   "+leftCount);
print("rightCount:  "+rightCount);
print("upCount:   	"+upCount);
print("downCount:   "+downCount);
print("leftUpCount: "+leftUpCount);
print("leftDownCount:   "+leftDownCount);
print("rightUpCount:   "+rightUpCount);
print("rightDownCount:   "+rightDownCount);
Debug.Log ("collector.COUNT: "+collectorOfPossibleMatches.Count);		
	}

void DestroyMatchingGems()
	{
		//Get all the gems on the screen with the TAG labled "Block".
		GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block"); 
	
		//Go through each gem in our FINAL list of gems to destroy off the board.
		foreach(GameObject gem in matchingListOfGemsToRemove)
		{
			//Save the x,y coords of the gem coming "out" blocks to temp variable
			int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
			int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
			// Set board tile we are going to destroy to empty (Zero)
			board[gemXpos,gemYpos] = 0; 
			//Destroy the gems in the final list of gems to get rid of off the board.
Debug.Log("gem:       "+gem);			
			Destroy (gem);
Debug.Log (" gemYpos-------------->: "+gemYpos);
Debug.Log (" gemXpos-------------->: "+gemXpos);			

		
			//Restack all gems on board if we just destroyed any and left empty spaces.
			
			foreach (GameObject restackGem in blocks)
					{
			//Save the x,y coords of the gem coming "out" blocks to temp variable
			int	restackGemXpos = Mathf.RoundToInt(restackGem.transform.position.x);
			int	restackGemYpos = Mathf.RoundToInt(restackGem.transform.position.y);
				
				if(restackGemYpos > gemYpos && restackGemXpos == gemXpos)
						{
							//Set old position to empty
							board[restackGemXpos,restackGemYpos] = 0;
							//Set new position on the BOARD
							board[restackGemXpos,restackGemYpos-1] = 1;
							//Move block down VISUALLY
							restackGem.transform.position = new Vector3(restackGemXpos, restackGemYpos-1, restackGem.transform.position.z);
						}
					}
				
		}
		matchingMaterial = null;
	}

And the biggest pain in the FOR LOOP butt…

//Check all 8 directions for neighboring gems of same kind.
void CheckNeighbors(GameObject startObject)
	{		
		//Get all the gems on the screen with the TAG labled "Block".
		GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block"); 
		//Get the current position x,y of the gem on the BOTTOM of the 3 dropping gems.
		int startObjectXpos = Mathf.RoundToInt(startObject.transform.position.x);
		int startObjectYpos = Mathf.RoundToInt(startObject.transform.position.y);
		
		//Look around cell at position startObjectXpos and startObjectYpos, from -1 to +1 in each direction
//Left
print ("checking LEFT....");
		leftCount = 0;
		for(int x = startObjectXpos-1 ; x < startObjectXpos; x--)
			{
				if (x < leftEdge)
				{
Debug.Log ("We hit the <---LEFT edge for checking, BREAK the check as we dont need to check off the board");				
				break; //if x is EDGE of board, then just cancel the check.	
				}
			//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,startObjectYpos]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(LEFT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("startObjectYpos: "+startObjectYpos);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == startObjectYpos)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
						if (isGemMatching == true)
						{
							leftCount ++;
						}
//We found the gem we were looking for, now break out of ("k")for loop as we dont need to check anymore from "blocks"
						break;
						}
					}
				}
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,startObjectYpos]==0)
					{
Debug.Log ("Grid Tile the the <---LEFT is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			if (isGemMatching==false)
				{
				break;
				}
			}
	
//Right
print ("checking Right....");
		rightCount = 0;
		for(int x = startObjectXpos+1 ; x > startObjectXpos; x++)
			{
				// if x is RIGHT EDGE of board, then just cancel the check.
				if (x > rightEdge)
				{
Debug.Log ("We hit the RIGHT---> edge for checking, BREAK the check as we dont need to check off the board");				
				break; 	
				}
			//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,startObjectYpos]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(RIGHT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("startObjectYpos: "+startObjectYpos);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == startObjectYpos)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
						if (isGemMatching == true)
						{
							rightCount ++;
						}
						break;
							//We want to test more blocks to the left untill we hit the edge of the board.
						}
					}
				}
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,startObjectYpos]==0)
					{
Debug.Log ("Grid Tile the the RIGHT---> is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			if (isGemMatching==false)
				{
				break;
				}
			}

		//Add up all the horizontal contiguous matches
			TallyHorzMatches();

//Up
print ("checking UP....");
		upCount = 0;
		for(int y = startObjectYpos+1 ; y > startObjectYpos; y++)
			{
				if (y > topEdge)
				{
Debug.Log ("We hit the TOP edge for checking, BREAK the check as we dont need to check off the board");				
				break; //RETURN? if y is EDGE of board, then just cancel the check.	
				}
			//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[startObjectXpos,y]==1)
				{
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("y: "+y);
Debug.Log ("startObjectXpos: "+startObjectXpos);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at x,y cords.
						
						//IF the gem coming out has cords that match our CURRENT direction x,y cords
						if(gemYpos == y && gemXpos == startObjectXpos)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
						if (isGemMatching == true)
							{
							upCount++;
							}
						//We dont want any more checking of the gems "in" blocks as we found the ONLY one we were looking for
						//and tested it.
						
						break; 
						}
					}
				}
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[startObjectXpos,y]==0)
					{
Debug.Log ("Grid Tile ABOVE^ is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			if (isGemMatching==false)
				{
				break;
				}
			}		

//Down
print ("checking DOWN....");
		downCount = 0;
		for(int y = startObjectYpos-1 ; y < startObjectYpos; y--)
			{
				if (y < bottomEdge)
				{
Debug.Log ("We hit the BOTTOM edge for checking, BREAK the check as we dont need to check off the board");				
				break; //if y is EDGE of board, then just cancel the check.	
				}
			//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[startObjectXpos,y]==1)
				{
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("y: "+y);
Debug.Log ("startObjectXpos: "+startObjectXpos);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at x,y cords.
						
						//IF the gem coming out has cords that match our CURRENT direction x,y cords
						if(gemYpos == y && gemXpos == startObjectXpos)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
						if (isGemMatching == true)
						{
							downCount ++;
						}
							//We dont want any more checking of the gems "in" blocks as we found the ONLY one we were looking for
						//and tested it.
						
						break; 
						}
					}
				}
			
				
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[startObjectXpos,y]==0)
					{
Debug.Log ("Grid Tile BELOW is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					return;
					}
			if (isGemMatching==false)
				{
				break;
				}
			}
		//Add up all the vertical contiguous matches
		TallyVertMatches();
/*
  * TODO: Fix diag checks to work correctly and store gems to destroy
   **/		
		
//Left & Up
print ("checking LEFT & UP....");
		leftUpCount = 0;
		for(int x = startObjectXpos-1 ; x < startObjectXpos; x--)
			{
				if (x < leftEdge)
				{
Debug.Log ("We hit the <---LEFT or TOP edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			int y = startObjectYpos+1;
			if (y > topEdge)
				{
Debug.Log ("We hit the <---LEFT or DOWN edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			
				if (y > startObjectYpos)
				{
	
		//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,y]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(LEFT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("y: "+y);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == y)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
							y++;
							if (isGemMatching == true)
						{
							leftUpCount ++;
						}
							break;
							//We want to test more blocks to the left untill we hit the edge of the board.
						}
					}
					
				}
			
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,y]==0)
					{
Debug.Log ("Grid Tile the the <---LEFT or UP is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			
			}

			if (isGemMatching==false)
				{
print ("SECOND isGemMatching check at end of FOR x");
				break;
				}	
	}

//Right & Down
print ("checking Right & DOWN....");
		rightDownCount = 0;
		for(int x = startObjectXpos+1 ; x > startObjectXpos; x++)
			{
				if (x > rightEdge)
				{
Debug.Log ("We hit the <---RIGHT or TOP edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			int y = startObjectYpos-1;
			if (y < bottomEdge)
				{
Debug.Log ("We hit the <---RIGHT or DOWN edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
				if (y < startObjectYpos)
				{
	
		//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,y]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(LEFT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("y: "+y);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == y)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
							y--;
							if (isGemMatching == true)
						{
							rightDownCount ++;
						}
							break;
							//We want to test more blocks to the left untill we hit the edge of the board.
						}
					}
					
				}
			
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,y]==0)
					{
Debug.Log ("Grid Tile the the <---RIGHT or UP is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			
			}

			if (isGemMatching==false)
				{
print ("SECOND isGemMatching check at end of FOR x");
				break;
				}	
		}		
		
//Left & Down
print ("checking LEFT & DOWN....");
		leftDownCount = 0;
		for(int x = startObjectXpos-1 ; x < startObjectXpos; x--)
			{
				if (x < leftEdge)
				{
Debug.Log ("We hit the <---LEFT or DOWN edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			int y = startObjectYpos-1;
			
	if (y < bottomEdge)
				{
Debug.Log ("We hit the <---LEFT or DOWN edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
				if (y < startObjectYpos)
				{
		//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,y]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(LEFT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("y: "+y);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == y)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
							//y--;
							if (isGemMatching == true)
						{
							leftDownCount ++;
								y--;
						}
							break;
							//We want to test more blocks to the left untill we hit the edge of the board.
						}
					}
					
				}
			
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,y]==0)
					{
Debug.Log ("Grid Tile the the <---LEFT or DOWN is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			
			}

			if (isGemMatching==false)
				{
print ("SECOND isGemMatching check at end of FOR x");
				break;
				}	
	}		

//Right & Up
print ("checking Right & UP....");
		rightUpCount = 0;
		for(int x = startObjectXpos+1 ; x > startObjectXpos; x++)
			{
				if (x > rightEdge)
				{
Debug.Log ("We hit the <---RIGHT or TOP edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			int y = startObjectYpos+1;
			if (y > topEdge)
				{
Debug.Log ("We hit the <---LEFT or DOWN edge for checking, BREAK the check as we dont need to check off the board");					
				break;
				}
			
				if (y > startObjectYpos)
				{
	
		//Make sure there is a GEM there at the x,y location on the board Tile we are looking at.	
			if(board[x,y]==1)
				{
				//Loop through all blocks checking each one until we get the gem NEAR(LEFT) to our Source gem.
				for (int k = 0; k<blocks.Length;k++)
					{
Debug.Log ("K: "+k);
					gem = blocks[k];
					//Store X and Y position of current gem being looked at from "blocks" 
						int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);
						int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);
					
Debug.Log ("gemXpos: "+gemXpos);
Debug.Log ("gemYpos: "+gemYpos);
Debug.Log ("x: "+x);
Debug.Log ("y: "+y);
						//Perform check on each gem coming "out" of blocks against our Board Tile we are looking at. x,y cord compare.
						
						//IF the gem coming out of blocks has cords that match our CURRENT direction x,y cords
						if(gemXpos == x && gemYpos == y)
						{
							//Then load the "gem" and call CheckGem(gem) to see if they have matching MATERIALS.
							CheckGem (gem);
							y++;
							if (isGemMatching == true)
						{
							rightUpCount ++;
						}
							break;
							//We want to test more blocks to the left untill we hit the edge of the board.
						}
					}
					
				}
			
			//If the board cords we are checking come up with an EMPTY Tile.	
			else if(board[x,y]==0)
					{
Debug.Log ("Grid Tile the the <---RIGHT or UP is EMPTY!(ZERO), return as there is an EMPTY tile.");
					// do nothing as there is NO gem in this current grid location.
					break;
					}
			
			}

			if (isGemMatching==false)
				{
print ("SECOND isGemMatching check at end of FOR x");
				break;
				}	
	}
		
	
	}	

Simple variables to keep track of number of matches.
//Tally up Matches for vertical
void TallyVertMatches()
{
if (upCount >= minNumOfGemsToCauseMatch - 1 || upCount + downCount >= minNumOfGemsToCauseMatch - 1 || downCount >= minNumOfGemsToCauseMatch - 1)
{

		foreach (GameObject gem in collectorOfPossibleMatches)
			{
				matchingListOfGemsToRemove.Add (gem);
Debug.Log ("matchingListOfGemsToRemove.COUNT:    "+matchingListOfGemsToRemove.Count);
Debug.Log ("matchingListOfGemsToRemove gems:    "+gem);				
			}
		}
	collectorOfPossibleMatches.Clear();
	}
	
//Tally up Matches for horizontal
void TallyHorzMatches()
	{
	if (leftCount >= minNumOfGemsToCauseMatch - 1 || rightCount >= minNumOfGemsToCauseMatch - 1 || leftCount+rightCount >= minNumOfGemsToCauseMatch-1)
		{
		foreach (GameObject gem in collectorOfPossibleMatches)
			{
				matchingListOfGemsToRemove.Add (gem);
Debug.Log ("matchingListOfGemsToRemove.COUNT:    "+matchingListOfGemsToRemove.Count);
			}
		}
	collectorOfPossibleMatches.Clear();
	}

This above is all the updated code i wrote yesterday. Thanks in advance folks.

I’ve decided to answer my own question as I have had only one reply to this post and I FINALLY got my routines working by myself…:slight_smile: Which leads me to new and more questions that I will post in another similar topic.
I’ve re-written everything to do with the match making about 9 times now, and I finally got it working as I already stated. I wanted to share what I found out, and I also have a few questions of my own.

The GOAL was and IS, to write the “BASE VERSION” of collumns written by SEGA for the genesis consoles.
I have the grid up, some “place holder” background picture, mock up gems (yeah dont laugh, they are UGLY!), no sound, but its all starting to come together. The biggest trouble to date that I have had with this project is the “Check Neighbors of Gems” part, and the stupid sort routine that hashes out all the CORRECT (3 or more) contiguous matches in the same row/collumn (in all 8 directions). I wrote my check neighbor routine to check for contiguous neighbors of neighbors and so on until there are no more gems matching that are left. I stored all my “gem finds” in a generic LIST and then i was done. (or not…) Thats great and works fine if your game is like any of the 2 million “Connect the same color of 3 or more contiguous tiles” games that are available! This one however only allows for contiguous connections of 3 or more tiles that are the same color,NEXT to each other, and are on the same line (horz,vert or diagonally). Now, keep in mind I have learned (been reminded? lol) and now know WHY all the unity admins and experienced coders are always “Screaming”:
“Think about how your going to setup and store your data now,(before you start to code) or later your most likely going to run into snags, delays, blah blah blah.” haha It was totally awesome having to put “Debug.Log” lines everywhere in the code to try and get some readings of what variable is doing what. In the beginning I had a butt load of “for loops” for the Check. it worked, but it was a mess and I kept having to use BREAK; statements to “kill” the loops. Eventually I was able to write my check neighbor helper method that used RECURSION (as was recommended to me to use) to check all the gems until none were left to check. On each pass of the neighbor gem check, I store all Horizontal gems that match in a seperate generic LIST, all Vertical gems in a seperate LIST, Diagonal gems in a seperate list. I have another LIST of gems that have already been checked so I DONT repeat checks of gems that have already been looked at by another “pass” of the check routine. I also use another LIST for a “ROLLING” list that keeps adding the gems that were “scooped up” by a check neighbor pass when a NEW base gem that had NOT been checked was found. I never know how big or small the rolling LIST is going to be until we are done with the recursion portion of the neighbor check routine. In the end I take one list at a time, for instance say, the list with only the HORZ matches in it… basically “take” the first gem out of said list, check its Y cord (up down) against all the rest of the gems in the horz match list. If there are 3 or more gems with the SAME Y cords, I dump/copy the “indexer” LIST of the 3 contiguous, same color, same column matches that my sort routine figured out, into a final list of match groups (indexes) that are to be destroyed. Then the final COMPLETE HORZ list of match groups is sent to my “Destroy object” helper method. The destroy helper method “looks” through the FINAL LIST OF indexes and ONLY destroys the gems in the horz list at the INDEX numbers given by the final list of match groups. Does that make sence? lol repeat for the vert,diag lists.

Here is what the goal was to check for tiles.
[35590-checkneighbortiles[1].jpg*_|35590]

Call the CheckForMatch when we stop or hit something:

//Check for a match
void CheckForMatch(GameObject startObject)
	{
		//Clear All LISTS to be used
		alreadyCheckedGems.Clear();
		rollingListOfAllNeighborGems.Clear ();
		horizontalMatchList.Clear ();
		verticalMatchList.Clear ();

		//Get the Material from the Gem that we are going to compare to for matches
		matchingMaterial = startObject.renderer.sharedMaterial;
		//Add the gem(s) to the already been checked list and the rolling list as we are checking it now.
		alreadyCheckedGems.Add (startObject);
		rollingListOfAllNeighborGems.Add(startObject);
		//Get all the gems on the player grid (not including the boarders) with the TAG labled "Block".
		GameObject[] blocks = GameObject.FindGameObjectsWithTag("Block");
		//Get the current position x,y of the base gem for checking
		int xPos = Mathf.RoundToInt(startObject.transform.position.x);
		int yPos = Mathf.RoundToInt(startObject.transform.position.y);
Debug.Log ("1st pass NON recursive CheckNeighbors  startObjectXPos: "+xPos+"   startObjectYPos:  "+yPos);
		//set the first pass codition so we know what LIST(s) to add our BASE GEM(s) too, so our counts are correct for each list (horz,vert,diags)
		isFirstPassOfBaseGem = true;
		//Check for matching neighbor gems in all 8 directions of our Base Gem
		CheckNeighbors(startObject, blocks);
		//Check to see if there is more then 1 gem in the rolling list (1 is the first that was added to ROLLING List and 
		//Already Been Checked List) if yes, that must mean we need to loop and check more gems, set WHILE condition to ALLOW the LOOP
//Debug.Log ("rollingListOfAllNeighborGems.Count: "+rollingListOfAllNeighborGems.Count);			
		if(rollingListOfAllNeighborGems.Count > 1 )
		{
			isCheckingNeighbors = true;
		}
//Loop continuously, checking neigbors, CHECKING NEIGHBORS OF NEIGHBORS, adding matching gems, until there are no more gems to check.
		//Make sure currentBaseGem is NOT NULL. If NULL, do NOT execute this WHILE LOOP!
		while (isCheckingNeighbors == true)
		{
			// find a new base gem that we've added to the rollingLIST but haven't analyzed yet
			for (int i = 0; i < rollingListOfAllNeighborGems.Count; i++)
				{
						currentBaseGem	= rollingListOfAllNeighborGems*;*

//Debug.Log (“SEARCHING FOR A NEW BASE GEM…LOOKING AT–>”
// +" currentBaseGem X: "+currentBaseGem.transform.position.x
// +" currentBaseGem Y: "+currentBaseGem.transform.position.y);

  •  				// If the alreadyCheckedGems has the gem "currentBaseGem" in it already*
    
  •  				if(alreadyCheckedGems.Contains(currentBaseGem))*
    
  •  					{*
    

//print(“THIS GEM HAS ALREADY BEEN USED AS A BASE GEM! CONTINUE SEARCHING FOR A NEW BASE GEM…”);

  •  					// check to see if we're on the last gem in the rollingList,if we are on the last gem,* 
    
  •  					//then there are no more base gem possibilities so we are done with the neighbor/match check.*
    
  •  					if(i == rollingListOfAllNeighborGems.Count - 1)*
    
  •  						{*
    
  •  						//No more matches, set EXIT condition*
    
  •  						isCheckingNeighbors = false;*
    
  •  						doRecursiveNeighborCheck = false;*
    
  •  						}*
    
  •  					}*
    
  •  				//not done with all gems in the ROLLING LIST and*
    
  •  				else*
    
  •  			//gem was NOT found in the Already Been Checked List so..*
    
  •  					{*
    
  •  					//There is another gem that has NOT already been checked, so make that our new "base gem"*
    
  •  					startObject = currentBaseGem;*
    
  •  					//Add it to the been checked LIST.*
    
  •  					alreadyCheckedGems.Add (startObject);*
    
  •  					doRecursiveNeighborCheck = true;*
    

_//print(“FOUND A NEW BASE GEM! USING NEW GEM FOR CHECKING NEIGHBORS…”); _

  •  					//We have a new gem that has not been tested, break the "for" loop!*
    
  •  					break;*
    
  •  					}*
    
  •  		}*
    
  •  	//RECURSION?*
    
  •  	if(doRecursiveNeighborCheck == true)*
    
  •  	{*
    
  •  	//Get the current position x,y of the base gem for checking*
    
  •  int tempxPos = Mathf.RoundToInt(startObject.transform.position.x);*
    
  •  int tempyPos = Mathf.RoundToInt(startObject.transform.position.y);*
    

_print ("RECURSIVE CheckNeighbors NEW BASE GEM tempxPos: “+tempxPos+” tempyPos: "+tempyPos); _

  •  		CheckNeighbors(startObject, blocks);*
    
  •  	}*
    
  •  }*
    
  •  //Clear our Temp list of gems that we use as an "Already Been Checked Gem" running List as we are going to re-use it below*
    
  •  alreadyCheckedGems.Clear();*
    

…more code…

Here is ONE direction of the CheckNeighbor of Neighbors:
//Check all 8 directions for neighboring gems of same kind.
void CheckNeighbors(GameObject startObject, GameObject[] blocks)

  • {*
  •  //Get the current position x,y of the base gem for checking*
    
  •  int xPos = Mathf.RoundToInt(startObject.transform.position.x);*
    
  •  int yPos = Mathf.RoundToInt(startObject.transform.position.y);*
    

#region 360DegreeDirectionalCheck

  •  	//Loop through ALL gems on the grid.*
    
  •  	for (int k = 0; k < blocks.Length; k++)*
    
  •  		{*
    
  •  		gem = blocks[k];*
    
  •  		//Store X and Y position of current gem being looked at from "blocks"* 
    
  •  		int	gemXpos = Mathf.RoundToInt(gem.transform.position.x);*
    
  •  		int	gemYpos = Mathf.RoundToInt(gem.transform.position.y);*
    
  •  	//Look around from -1 to +1 in each of the 8 directions*
    
  •  	// 1 or higher = a gem is there, what kind we dont know yet, I.E. (1) Normal gem (2)Special gem (3)etc...* 
    
  •  	//REFERENCE: SpawnShape(int forceSpawnOfGemType)*
    

*//Left *

  •  	if(board[xPos-1,yPos] >= 1 &&*
    
  •  			//AND on each gem coming "out" of blocks compare its x,y cords to the tile cords in direction we are looking at,*
    
  •  			gemXpos == xPos-1 &&*
    
  •  			gemYpos == yPos)*
    
  •  		{*
    

print (“checking LEFT…”);

  •  			//If the gem is NOT in the rolling list already...*
    
  •  			if(!rollingListOfAllNeighborGems.Contains(gem))*
    
  •  			{*
    
  •  				//Check to see if the gem has matching MATERIALS.*
    
  •  				CheckGem (gem);*
    
  •  				//If Materials DO match*
    
  •  				if (isGemMatching == true &&*
    
  •  					//AND if the horzMatchList does NOT contain the gem already*
    
  •  					!horizontalMatchList.Contains(gem) )*
    
  •  				{*
    
  •  					//Add the gem to its appropriate LIST.*
    
  •  					horizontalMatchList.Add(gem);*
    
  •  					if (isFirstPassOfBaseGem == true)*
    
  •  					{*
    
  •  					horizontalMatchList.Add(startObject);*
    
  •  					//Done with first pass, we dont want to add the very first base gem to any lists after this, until a NEW check for match call is performed*
    
  •  					isFirstPassOfBaseGem = false;*
    
  •  					}*
    
  •  				}*
    
  •  			}*
    
  •  			//The gem is ALREADY in the Rolling List. No need to do any further checks on this gem*
    
  •  			else*
    
  •  			{*
    
  •  			}*
    
  •  		}*
    

//Right
…more code…

Here is the Code snip for the List sorting:
//* FINAL LIST MANIPULATION *
//********************************

  • if(horizontalMatchList.Count >= minNumOfGemsToCauseMatch)*
  •  {*
    
  •  	for (int i = 0; i < horizontalMatchList.Count; i++)*
    
  •  		{*
    
  •  		//Get the gem at "i" in the list*
    

_ obj = horizontalMatchList*;_
_
//already been checked does NOT contain the gem…_
_
if(!alreadyCheckedGems.Contains(obj))_
_
{_
_
//Add it to the been checked LIST._
_
alreadyCheckedGems.Add (obj);_
_
//Get the current position x,y of the base gem for checking*_
* //int objXPos = Mathf.RoundToInt(obj.transform.position.x);*
* int objYPos = Mathf.RoundToInt(obj.transform.position.y);*

* for(int k = 0; k < horizontalMatchList.Count; k++)*
* {*
* gem = horizontalMatchList[k];*

* //int gemXPos = Mathf.RoundToInt(obj.transform.position.x);*
* int gemYPos = Mathf.RoundToInt(gem.transform.position.y);*

* if(gemYPos == objYPos)*
* {*
* matchGroup.Add(k);*
* alreadyCheckedGems.Add(gem);*
* }*
* }*
* if(matchGroup.Count >= minNumOfGemsToCauseMatch)*
* {*
* //add all 3 or more matches that were found to the “final list of horz” matches to destroy*
* finalMatchGroup.AddRange(matchGroup);*
* //clear matchgroup temp list as we are going to look for a new match group*
* matchGroup.Clear();*
* }*
* //clear matchgroup temp list as there were NOT enough gems to make a horz CONTIGUOUS match of 3 or more!*
* matchGroup.Clear();*
* }*
* }*
* //done with horz contiguous match sorting*
* if(finalMatchGroup.Count >= minNumOfGemsToCauseMatch)*
* {*
//print (“HORIZONTALLY WE HIT A CHAIN OF 3 OR MORE!”);
* //Destroy gems if there are 3 or more matches*
* DestroyMatchingGems(horizontalMatchList, blocks);*
* horizontalMatchList.Clear();*
* finalMatchGroup.Clear();*
* alreadyCheckedGems.Clear ();*
* obj = null;*
* gem = null;*
* }*
* }*
…more code…

Here is the Code for my Destroy gem routine:

//Destroy FINAL list of contiguous matching gems and RESTACK the gems on playing board. Send the LIST to destroy INTO the helper method
void DestroyMatchingGems(List matchingListOfContiguousGemsToRemove, GameObject[] blocks )
* {*
* //Go through each INDEX NUMBER from our Temp “final” group matches List and Destroy the gem in the LIST SENT TO THIS METHOD.*
* for(int i=0; i < finalMatchGroup.Count;i++)*
* {*
_ int indexer = finalMatchGroup*;
gem = matchingListOfContiguousGemsToRemove[indexer];*_

* int tempGemXpos = Mathf.RoundToInt(gem.transform.position.x);*
* int tempGemYpos = Mathf.RoundToInt(gem.transform.position.y);*

* //Set old position to empty*
* board[tempGemXpos,tempGemYpos] = 0;*
* //Destroy gem in list - repeat process for all gems in LIST*
* Destroy(gem);*
* }*
* matchingListOfContiguousGemsToRemove.Clear();*

* }*

Here is the Picture of the test playfield:
the gaps in the grid are from the destroy gem function getting rid of the gems, but not moving the rest of the board down yet…
[35592-playergridwithgems.jpg|35592]
Read more in the responses for my next questions relating to this?
Sorry for the sloppy code, and all the comments left in the code itself,but I just wanted to get this posted.
Thanks
King

_*