Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Resolved 2D 2048 type of a game: game objects moving moving underneat/ontop of each other.

Discussion in 'Scripting' started by Scadie, Jan 1, 2021.

  1. Scadie

    Scadie

    Joined:
    Jan 20, 2019
    Posts:
    5
    Hi!

    This is going to be the first game I've ever done by myself. The game is in a 5x5 grid and the game objects are supposed to move left, right, up down as long as there isn't a game object within that coordinate already. I ran into a problem, where if I have 3 or more game pieces in a row they move underneath/on top of each other. This does not happen when I only have 2 game pieces.

    Two pieces move like this:


    Four Pieces move like this:


    And here's the code.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using Unity.Mathematics;
    5. using UnityEditor.Experimental.GraphView;
    6. using UnityEngine;
    7. using UnityEngine.PlayerLoop;
    8. using UnityEngine.SocialPlatforms;
    9.  
    10.  
    11. public class GamePiece : MonoBehaviour
    12. {
    13.     [SerializeField] private float maxX = 2;
    14.     [SerializeField] private float minX = -2;
    15.     [SerializeField] private float maxY = 2;
    16.     [SerializeField] private float minY = -2;
    17.     private Grid myGrid;
    18.     private Vector2 checkBoxSize = new Vector2(0.3f, 0.3f);
    19.  
    20.  
    21.     private void Start()
    22.     {
    23.         myGrid = FindObjectOfType<Grid>();
    24.        
    25.     }
    26.  
    27.  
    28.     private void Update()
    29.     {
    30.         MovePiece();
    31.        
    32.     }
    33.    
    34.  
    35.     private void MovePiece()
    36.     {
    37.         bool getRightKeyDown = Input.GetKeyDown("right");
    38.         bool getLeftKeyDown = Input.GetKeyDown("left");
    39.         bool getUpKeyDown = Input.GetKeyDown("up");
    40.         bool getDownKeyDown = Input.GetKeyDown("down");
    41.    
    42.         bool PieceHasMoved = false;
    43.      
    44.        
    45.         if (getRightKeyDown)
    46.         {
    47.        
    48.             for (float rightMovement = transform.position.x; rightMovement < maxX; rightMovement++)
    49.             {
    50.                 if (Physics2D.OverlapBox(new Vector2(rightMovement+1, transform.position.y), checkBoxSize, 0))
    51.                 {
    52.                     transform.position = new Vector2(rightMovement, transform.position.y);
    53.                     PieceHasMoved = true;
    54.                 }
    55.                
    56.             }
    57.            
    58.            
    59.             if (!PieceHasMoved)
    60.             {
    61.                 transform.position = new Vector2(maxX, transform.position.y);
    62.             }
    63.         }
    64.        
    65.         if (getLeftKeyDown)
    66.         {
    67.             for (float leftMovement = transform.position.x; leftMovement > minX; leftMovement--)
    68.             {
    69.                 if (Physics2D.OverlapBox(new Vector2(leftMovement-1, transform.position.y), checkBoxSize, 0))
    70.                 {
    71.                     transform.position = new Vector2(leftMovement, transform.position.y);
    72.                     PieceHasMoved = true;
    73.                 }
    74.                
    75.             }
    76.  
    77.             if (!PieceHasMoved)
    78.             {
    79.                 transform.position = new Vector2(minX, transform.position.y);
    80.             }
    81.         }
    82.        
    83.         if (getUpKeyDown)
    84.         {
    85.             for (float upMovement = transform.position.y; upMovement < maxY; upMovement++)
    86.             {
    87.                 if (Physics2D.OverlapBox(new Vector2(transform.position.x, upMovement+1), checkBoxSize, 0))
    88.                 {
    89.                     transform.position = new Vector2( transform.position.x , upMovement);
    90.                     PieceHasMoved = true;
    91.                 }
    92.                
    93.             }
    94.  
    95.             if (!PieceHasMoved)
    96.             {
    97.                 transform.position = new Vector2(transform.position.x , maxY);
    98.             }
    99.         }
    100.        
    101.         if (getDownKeyDown)
    102.         {
    103.             for (float downMovement = transform.position.y; downMovement > minY; downMovement--)
    104.             {
    105.                 if (Physics2D.OverlapBox(new Vector2(transform.position.x, downMovement-1), checkBoxSize, 0))
    106.                 {
    107.                     transform.position = new Vector2( transform.position.x , downMovement);
    108.                     PieceHasMoved = true;
    109.                 }
    110.                
    111.             }
    112.  
    113.             if (!PieceHasMoved)
    114.             {
    115.                 transform.position = new Vector2(transform.position.x , minY);
    116.             }
    117.         }
    118.  
    119.      
    120.     }
    121.  
    122.   }
    So any tips how do I get the pieces to not stack on top of each other are welcome. Also If there's a mechanism, to call the method repeatedly to make the pieces move to their correct location with one button press that would be great. But I think I can figure that out on my own with something like coroutine.

    Thanks in advance! Keep in mind I'm a total beginner, and new to the ways of coding, so ELI5 if possible :)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,780
    There are three ways to layer things in Unity, depending on what approach you are using:

    - sprites - explicit draw order (sorting order, sorting layer)

    - UI elements rendered by CanvasRenderer: the order in the hierarchy, possibly overridden by canvases

    - world / 3D and the "regular" shaders: the Z order

    Generally you want to stick with ONE method, otherwise you need to take extra measures to get sorting proper across different domains of sorting approaches.

    I can't tell from the code above which method you are using.
     
  3. Scadie

    Scadie

    Joined:
    Jan 20, 2019
    Posts:
    5
    The shapes are sprite shapes. So 2d object -> sprite shape. They are all on default layer with no tags. All of the game pieces are on the sorting layer called: "game". All of the objects Z coordinate is 0.
    I am, as of now, using no canvases.

    As I instantiate new game pieces the problem repeats itself. Whenever I have more than 2 pieces in a row or column they stack.
    Illustration:

     
  4. Scadie

    Scadie

    Joined:
    Jan 20, 2019
    Posts:
    5
    Figured it out: had to break out of the for loop.

    For those curious:

    So the code snippet below, when right arrow key is pressed, checks whether there is a collider in the coordinate to the right of the game piece. If there is, it will move the piece one step to the left from the collider that was detected. This however did not break the loop, so the piece always ended up in the second to last square.

    So say I have a pieces in 0,0 (middle); 1,0 and 2, 0. When pressing the right arrow key, the piece in 2,0 will stand still since its already in the max coordinate. piece 1,0 will check that there's a piece next to it and be moved to the same position that it is in already.

    0,0 will check that it there's a piece next to it (1,0) and will be moved to 0,0 and then it also checks that there's a piece in 2,0 and will be moved to 1,0. Therefore stacking the pieces if there are more than two in a row or a collumn.

    Code (CSharp):
    1. private void MovePiece()
    2.     {
    3.         bool getRightKeyDown = Input.GetKeyDown("right");
    4.         bool getLeftKeyDown = Input.GetKeyDown("left");
    5.         bool getUpKeyDown = Input.GetKeyDown("up");
    6.         bool getDownKeyDown = Input.GetKeyDown("down");
    7.  
    8.         bool PieceHasMoved = false;
    9.    
    10.      
    11.         if (getRightKeyDown)
    12.         {
    13.      
    14.             for (float rightMovement = transform.position.x; rightMovement < maxX; rightMovement++)
    15.             {
    16.                 if (Physics2D.OverlapBox(new Vector2(rightMovement+1, transform.position.y), checkBoxSize, 0))
    17.                 {
    18.                     transform.position = new Vector2(rightMovement, transform.position.y);
    19.                     PieceHasMoved = true;
    20.                 }
    21.              
    22.             }
    23.          
    24.          
    25.             if (!PieceHasMoved)
    26.             {
    27.                 transform.position = new Vector2(maxX, transform.position.y);
    28.             }
    29.         }
    So all that was needed to fix the issue was to add the statement:
    break;

    Like so

    Code (CSharp):
    1.  for (float rightMovement = transform.position.x; rightMovement < maxX; rightMovement++)
    2.             {
    3.                 if (Physics2D.OverlapBox(new Vector2(rightMovement+1, transform.position.y), checkBoxSize, 0))
    4.                 {
    5.                     transform.position = new Vector2(rightMovement, transform.position.y);
    6.                     PieceHasMoved = true;
    7.                     break;
    8.                 }
    9.              
    10.             }
     
    Kurt-Dekker likes this.