Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Match Mechanic Help

Discussion in 'Scripting' started by JacksonTheXtremeGamer, Jul 22, 2019.

  1. JacksonTheXtremeGamer

    JacksonTheXtremeGamer

    Joined:
    Jun 15, 2019
    Posts:
    108
    I’ve been trying hard to figure out how to make the match mechanic, but have not come across a situation where the mechanic is broken or that errors pop up on my script. I’m stumped. People tell me I need a 2d array of some sort. But what am I supposed to look at? How can I make the grid check for a horizontal of vertical match 3?
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    It would really help if you told us a little bit more about what you are trying to do, and showed the code you already have. Remember that the issue you are working at is new to us, as we are all working on different things. Also note that you have not told us anything about additional contraints, so all you are asking is for a simple way to find if you have a match of three either horizontal or vertically. I'm therefore assuming that the grid is filled with a Maximum of one such occurence.

    That being said, yes, you'll need a grid. I recommend you take a grid paper to initially model the Problem. Number the axes (top-down and across) from 0 to 9, so you can identify each field, e.g. (3, 8) is the field 3 across, 8 down. The numbering will be identical to how you access the array (I stongly suggest you read up on Arrays).

    Now, how would you find if there are three items in a grid horizontal or vertical? The issue can become quite simple if you look at it the right way, but become very complex if you don't.

    Take a pen to your grid, and fill in the two possible configurations where such an event occurs - horizontal and vertical.

    Now, the intuitive approach would be to look at this and say: OK, if I have a grid Position occupied at (3,8), i can simply check if its neighbour to the right (at 4,8) is also occupied, and if that is occupied, check if the one next to that (5, 8) is also occupied (note that the horizontal index increases predictably: 3-4-5). If so, you have a match. If that fails, do the same for down. So write a simple function lookRightAtGridPosition(x,y) that returns true or false for any grid position if there are three horizontally, and another one lookDownAtGridPosition(x,y) that'll do the same looking down.

    You scan the entire board for all x and y until you find a three-match, or until you have completed the scan. When you scan, remember that your scan must correctly handle the edge cases: When you start at (3,8) and start looking down, you'll find that if you go down two rows, you'll cross the limits of grid, which will create an error. So you may be tempted to only scan the board in the 0 though 7 range both horizontally and vertically. but that will leave a two Units wide stripe on the sides that could contain 3-matches in the not-scanned for direction (down on the side, right at the bottom). You'll need to code for that separately.
     
  3. JacksonTheXtremeGamer

    JacksonTheXtremeGamer

    Joined:
    Jun 15, 2019
    Posts:
    108
    It’s a match 3 game where you drop blocks in a 5 by 8 grid. The controls are simple, left and right to move the block, and down to scroll to the bottom. And surprisingly enough the pieces are a single unit. And right now, I’m using 6 colors: Red, Orange, Yellow, Green, Blue, and Purple. I’m making a prototype for it, but I still need that piece. Once I have that and the prototype is complete, I plan to make it a single-player campaign game for itch release. But before that, I would have to take a break, as this is giving my head a run for its money.
     
  4. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    well, you are all set then :)
     
  5. JacksonTheXtremeGamer

    JacksonTheXtremeGamer

    Joined:
    Jun 15, 2019
    Posts:
    108
    Well JUST to be sure you know what the absolute balls I'm talking about, it's this:
    Example.PNG
    The position (0,0) is the bottom left corner. Keep in mind that this is like puzzle league.
     
  6. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Right. All that you now need to do is write the code. And if you have a specific problem, describe it, post the code, and we’ll do our best to help you.
     
  7. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    Well, for all (x,y) from (0,0) to (height - 3, width-3) check if pieces at (x+1, y), (x+2, y) or (x,y+1. x, y+2) are of the same color. If they are, score, destroy, drop down all pieces having empty square underneath. Sounds pretty easy task. What is the problem?
     
  8. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Actually. it's slightly more involved (but not much) because you need to check the last two columns for 3-aligned vertical, nd the last two rows for 3-aligned horizontal. But other than that,I agree, easy.
     
    palex-nx likes this.
  9. JacksonTheXtremeGamer

    JacksonTheXtremeGamer

    Joined:
    Jun 15, 2019
    Posts:
    108
    Well for starters, here's the code for the grid and the pieces:
    Code (CSharp):
    1. public class Board : MonoBehaviour
    2. {
    3.     public static int gridwidth = 5;
    4.     public static int gridheight = 12;
    5.  
    6.     public static Transform[,] grid = new Transform[gridwidth, gridheight];
    7.  
    8.     // Use this for Initialization
    9.     void Start()
    10.     {
    11.         SpawnNextPiece();
    12.     }
    13.  
    14.     // Update is called once per frame
    15.     void Update()
    16.     {
    17.  
    18.     }
    19.     public void UpdateGrid(Piece piece)
    20.     {
    21.         for (int y = 0; y < gridheight; ++y)
    22.         {
    23.             for (int x = 0; x < gridwidth; ++x)
    24.             {
    25.                 if (grid[x, y] != null)
    26.                 {
    27.                     if (grid[x, y].parent == piece.transform)
    28.                     {
    29.                         grid[x, y] = null;
    30.                     }
    31.                 }
    32.             }
    33.         }
    34.         foreach (Transform block in piece.transform)
    35.         {
    36.             Vector2 pos = Round(block.position);
    37.             if (pos.y < gridheight)
    38.             {
    39.                 grid[(int)pos.x, (int)pos.y] = block;
    40.             }
    41.         }
    42.     }
    43.     public Transform GetTransformAtGridPosition(Vector2 pos)
    44.     {
    45.         if (pos.y > gridheight - 1)
    46.         {
    47.             return null;
    48.         }
    49.         else
    50.         {
    51.             return grid[(int)pos.x, (int)pos.y];
    52.         }
    53.     }
    54.     public void SpawnNextPiece()
    55.     {
    56.         GameObject nextPiece = (GameObject)Instantiate(Resources.Load(GetRandomPiece(), typeof(GameObject)), new Vector2(2.0f, 10.0f), Quaternion.identity);
    57.     }
    58.     public bool CheckIsInsideGrid (Vector2 pos)
    59.     {
    60.         return ((int)pos.x >= 0 && (int)pos.x < gridwidth && (int)pos.y >= 0);
    61.     }
    62.     public Vector2 Round (Vector2 pos)
    63.     {
    64.         return new Vector2(Mathf.Round(pos.x), Mathf.Round(pos.y));
    65.     }
    66.  
    67.     private string GetRandomPiece()
    68.     {
    69.         int randomPiece = Random.Range(1, 7);
    70.         string randomPieceName = "Prefabs/Red";
    71.         switch (randomPiece)
    72.         {
    73.             case 1:
    74.                 randomPieceName = "Prefabs/Red";
    75.                 break;
    76.             case 2:
    77.                 randomPieceName = "Prefabs/Orange";
    78.                 break;
    79.             case 3:
    80.                 randomPieceName = "Prefabs/Yellow";
    81.                 break;
    82.             case 4:
    83.                 randomPieceName = "Prefabs/Green";
    84.                 break;
    85.             case 5:
    86.                 randomPieceName = "Prefabs/Blue";
    87.                 break;
    88.             case 6:
    89.                 randomPieceName = "Prefabs/Purple";
    90.                 break;
    91.         }
    92.         return randomPieceName;
    93.     }
    94. }
    95.  
    Code (CSharp):
    1. public class Piece : MonoBehaviour
    2. {
    3.     float fall = 0;
    4.     public float fallSpeed = 1;
    5.     //Use this for initialization
    6.     void Start()
    7.     {
    8.      
    9.     }
    10.  
    11.     // Update is called once per frame
    12.     void Update()
    13.     {
    14.         CheckUserInput();
    15.     }
    16.     void CheckUserInput()
    17.     {
    18.  
    19.         if (Input.GetKeyDown(KeyCode.RightArrow))
    20.         {
    21.             transform.position += new Vector3(1, 0, 0);
    22.             if (CheckIsValidPosition())
    23.             {
    24.                 FindObjectOfType<Board>().UpdateGrid(this);
    25.             }
    26.             else
    27.             {
    28.                 transform.position += new Vector3(-1, 0, 0);
    29.             }
    30.         }
    31.         else if (Input.GetKeyDown(KeyCode.LeftArrow))
    32.         {
    33.             transform.position += new Vector3(-1, 0, 0);
    34.             if (CheckIsValidPosition())
    35.             {
    36.                 FindObjectOfType<Board>().UpdateGrid(this);
    37.             }
    38.             else
    39.             {
    40.                 transform.position += new Vector3(1, 0, 0);
    41.             }
    42.         }
    43.         else if (Input.GetKeyDown(KeyCode.DownArrow))
    44.         {
    45.             transform.position += new Vector3(0, -1, 0);
    46.             if (CheckIsValidPosition())
    47.             {
    48.                 FindObjectOfType<Board>().UpdateGrid(this);
    49.             }
    50.             else
    51.             {
    52.                 transform.position += new Vector3(0, 1, 0);
    53.                 enabled = false;
    54.                 FindObjectOfType<Board>().SpawnNextPiece();
    55.             }
    56.          
    57.         }
    58.     }
    59.     bool CheckIsValidPosition()
    60.     {
    61.         foreach (Transform unit in transform)
    62.         {
    63.             Vector2 pos = FindObjectOfType<Board>().Round (unit.position);
    64.  
    65.             if (FindObjectOfType<Board>().CheckIsInsideGrid (pos) == false)
    66.             {
    67.                 return false;
    68.             }
    69.             if (FindObjectOfType<Board>().GetTransformAtGridPosition(pos) != null && FindObjectOfType<Board>().GetTransformAtGridPosition(pos).parent != transform)
    70.                 {
    71.                 return false;
    72.             }
    73.         }
    74.         return true;
    75.     }
    76. }
    The code is based off of a Tetris tutorial I looked up. The main problem is where to put it and how to make the code work without errors popping up in my face on Visual. I found one idea from this link here, but my mind can only take so much. Bottom line though, will this work?
    https://www.reddit.com/r/Unity3D/comments/6qsid5/how_to_detect_matches_in_match3_game/
     
  10. JacksonTheXtremeGamer

    JacksonTheXtremeGamer

    Joined:
    Jun 15, 2019
    Posts:
    108