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 :) 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? :)
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? :)
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 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 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 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 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 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= 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.
↧