How to Identify and Count Prefabs Collision in Unity

Asked

Viewed 1,825 times

7

I am developing a game for android on the platform Unity that is similar to the game Tetris, the difference that is geared to chemistry, and instead of descending the tetrominos will descend the elements to compose a molecule. Well, what logic am I trying to apply: to form a carbon it is necessary that the C has 4 H around it to close. From there I used flags for prefabs carbons and for hydrogen. My idea is when to go down the C, check if there is the C, hence it goes to the next conditions, which is to know if there is an H in any of its sides, when the counter reaches 4 is because the C closed with the 4 H. However, in practice it did not work. Can anyone help me with that logic, or give me an easier suggestion? In the image below the C is composed by 4 H, so it was to punctuate and delete these 5 pieces(4 H and the C).

erro

he’s not doing the checks;

inserir a descrição da imagem aqui

And here’s my code:

public void Checks(){

    for (int y = 0; y < gridHeight; ++y) {
        for (int x = 0; x < gridWidth; ++x) {
            if (Grid [x, y] != null) {

                if (Grid [x, y].tag == "CARBONO") {
                    Debug.Log ("EXISTE C: ");
                    if (Grid [x + 1, y].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x - 1, y].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x, y + 1].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x, y - 1].tag == "HIDROGENIO") {
                        cont++;
                    }
                }
                Debug.Log ("contador: " + cont); //teste
            }
        }
    }
}

GAME class:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class Game : MonoBehaviour {

public static int gridWidth = 10;
public static int gridHeight = 20;
public static Transform[,] Grid = new Transform[gridWidth, gridHeight];
public static Tetromino[,] model = new Tetromino[gridWidth, gridHeight];
private GameObject previewTetromino;
private GameObject nextTetromino;
private bool gameStarted = false;
public int scoreOneLine = 40;
public int scoreTwoLine = 100;
public int cont = 0;
private int numerOfRowsThisTurn = 0;
public Text hud_score;
public static int currentScore = 0;
private Vector2 previewTetrominoPosition = new Vector2 (13.88f, 11.08f);


// Use this for initialization
void Start () {
    SpawnNextTetromino ();


    //AudioSource = GetComponent<AudioSource> ();
} 

void Update () {
    Checks ();
    UpdateScore ();
    UpdateUI ();
}

// Update is called once per frame
public void UpdateScore(){
    if (numerOfRowsThisTurn > 0) {

        if (numerOfRowsThisTurn == 1) {
            ClearedOneLine ();
        } else if (numerOfRowsThisTurn == 2) {
            ClearedTwoLine ();
        }
        numerOfRowsThisTurn = 0;
    }
}

public void Checks(){

    for (int y = 0; y < gridHeight; ++y) {
        for (int x = 0; x < gridWidth; ++x) {
            if (Grid [x, y] != null) {

                if (Grid [x, y].tag == "CARBONO") {
                    Debug.Log ("EXISTE C: ");
                    if (Grid [x + 1, y].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x - 1, y].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x, y + 1].tag == "HIDROGENIO") {
                        cont++;
                    }
                    if (Grid [x, y - 1].tag == "HIDROGENIO") {
                        cont++;
                    }
                }
                Debug.Log ("contador: " + cont); //teste
            }
        }
    }
}

public void UpdateUI(){
    hud_score.text = currentScore.ToString ();
}



public void ClearedOneLine(){
    currentScore += scoreOneLine;
}
public void ClearedTwoLine(){
    currentScore += scoreTwoLine;
}

public bool CheckIsAboveGrid(Tetromino tetromino){
    for(int x = 0; x < gridWidth; ++x){
        foreach(Transform mino in tetromino.transform){
            Vector2 pos = Round (mino.position);
            if(pos.y > gridHeight - 1){
                return true;
            }
        }
    }
    return false;
}

public bool IsFullRowAt(int y){
    for (int x = 0; x < gridWidth; ++x){
        if(Grid[x,y] = null){
            return false;
        }
    }
    numerOfRowsThisTurn++;
    return true;
}

public void updateGrid (Tetromino tetromino) {
    for (int y = 0; y <gridHeight; ++y) {
        for (int x = 0; x <gridWidth; ++x) {
            if (Grid [x, y] != null) {
                if (Grid [x, y].parent == tetromino.transform) {
                    Grid [x, y] = null;
                    model [x, y] = null;
                }
            }
        }
    }
    foreach (Transform mino in tetromino.transform) {
        Vector2 pos = Round (mino.position);
        if (pos.y < gridHeight) {
            Grid [(int)pos.x, (int)pos.y] = mino;
            model [(int)pos.x, (int)pos.y] = tetromino;
        }
    }
}
public Transform GetTransformAtGetPosition (Vector2 pos) {
    if (pos.y > gridHeight - 1) {
        return null;
    } else {
        return Grid [(int)pos.x, (int)pos.y];
    }

}

public void SpawnNextTetromino () {
    if (!gameStarted) {

        gameStarted = true;
        nextTetromino = (GameObject)Instantiate(Resources.Load(GetRandomTetromino(), typeof(GameObject)), new Vector2 (5.0f, 22.0f), Quaternion.identity);
        previewTetromino = (GameObject)Instantiate (Resources.Load (GetRandomTetromino (), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
        previewTetromino.GetComponent<Tetromino> ().enabled = false;

    } else {
        previewTetromino.transform.localPosition = new Vector2 (5.0f, 20.0f);
        nextTetromino = previewTetromino;
        nextTetromino.GetComponent<Tetromino> ().enabled = true;

        previewTetromino = (GameObject)Instantiate (Resources.Load (GetRandomTetromino (), typeof(GameObject)), previewTetrominoPosition, Quaternion.identity);
        previewTetromino.GetComponent<Tetromino> ().enabled = false;
    }

}


public bool CheckIsInsideGrid (Vector2 pos){
    return ((int)pos.x >= 0 && (int)pos.x < gridWidth && (int)pos.y >= 0);
}

public Vector2 Round (Vector2 pos){
    return new Vector2 (Mathf.Round(pos.x), Mathf.Round(pos.y));
}

string GetRandomTetromino(){
    int randomTetromino = Random.Range (1, 5);
    string randomTetrominoName = "Prefabs/C";
    switch (randomTetromino) {
    case 1:
        randomTetrominoName = "Prefabs/H";

        break;
    case 2:
        randomTetrominoName = "Prefabs/C";
        break;
    case 3:
        randomTetrominoName = "Prefabs/H";
        break;
    case 4:
        randomTetrominoName = "Prefabs/C";
        break;

    }
    return randomTetrominoName;


}

TETROMINO CLASS:

using UnityEngine;
using System.Collections;

public class Tetromino : MonoBehaviour {

float fall = 0;
public float fallSpeed = 2;
public bool allowRotation = true;
public bool limitRoatation = false;

public int individualScore = 100;
private float individualScoreTime;

public static int UP = 1;  
public static int DOWN = 2;
public static int RIGHT = 3;
public static int LEFT = 4;
private bool visited = false;
private bool fullConection = false;
private Tetromino[] connections = new Tetromino[4];


// Update is called once per frame
void Update () {

    CheckUserInput ();
    UpdateIndividualScore ();
}

public void UpdateIndividualScore(){

    if (individualScoreTime < 1) {

        individualScoreTime += Time.deltaTime;

    } else {

        individualScoreTime = 0;

        individualScore = Mathf.Max (individualScore - 10, 0);
    }
}
public void CheckUserInput () {
            if (Input.GetKeyDown(KeyCode.RightArrow)) {

                transform.position += new Vector3(1, 0, 0);

                if (CheckIsValidPosition()) {

                    FindObjectOfType<Game>().updateGrid(this);
                    FindObjectOfType<Game> ().Checks ();
                } else {

                    transform.position += new Vector3(-1, 0, 0);
                }

            } else if (Input.GetKeyDown(KeyCode.LeftArrow)) {

                transform.position += new Vector3(-1, 0, 0);

                if (CheckIsValidPosition()) {

                    FindObjectOfType<Game>().updateGrid(this);
                    FindObjectOfType<Game> ().Checks ();
                } else {

                    transform.position += new Vector3(1, 0, 0);
                }
            } else if (Input.GetKeyDown(KeyCode.UpArrow)) {

                if (allowRotation) {

                    if (limitRoatation) {

                        if (transform.rotation.eulerAngles.z >= 90) {

                            //transform.Rotate(0, 0, -90);

                        } else {

                            //transform.Rotate(0, 0, 90);
                        }
                    } else {
                        transform.Rotate (0, 0, 90);
                    }

                    if (CheckIsValidPosition()) {

                        FindObjectOfType<Game>().updateGrid(this);
                        FindObjectOfType<Game> ().Checks ();
                    } else {

                        if (transform.rotation.eulerAngles.z >= 90) {

                            //transform.Rotate(0, 0, -90);

                        } else {
                            /*if (limitRoatation) {
                                transform.Rotate (0, 0, 90);

                            }*/

                            //transform.Rotate (0, 0, -90);
                        }
                    }
                }

            } else if (Input.GetKeyDown(KeyCode.DownArrow) || Time.time - fall >= fallSpeed) {

                transform.position += new Vector3(0, -1, 0);

                if (CheckIsValidPosition()) {

                    FindObjectOfType<Game>().updateGrid(this);
                    //FindObjectOfType<Game> ().Checks ();

                } else {

                    transform.position += new Vector3(0, 1, 0);

                    if (FindObjectOfType<Game> ().CheckIsAboveGrid (this)) {
                        FindObjectOfType<Game> ().GameOver ();
                    }

                    enabled = false;


                    FindObjectOfType<Game> ().updateConnection (this);
                    FindObjectOfType<Game> ().Checks ();
                    FindObjectOfType<Game> ().SpawnNextTetromino ();

                    Game.currentScore += individualScore;


                }

                fall = Time.time;
            }
        }

bool CheckIsValidPosition () {

    foreach (Transform mino in transform) {

    Vector2 pos = FindObjectOfType<Game>().Round (mino.position);

    if (FindObjectOfType<Game>().CheckIsInsideGrid (pos) == false) {

            return false;
        }

        if (FindObjectOfType<Game>().GetTransformAtGetPosition(pos) != null && FindObjectOfType<Game>().GetTransformAtGetPosition(pos).parent != transform) {

            return false;
        }
    }

    return true;
}
  • 1

    Give more details on how you’ve done the project. For example, are you using Unity physics (like, do the elements "fall" using physics, or do you translate manually?)? Depending on your approach, there are different possible answers/suggestions.

  • To help you, you need more information as @Luizvieira said.

  • Just a hint, whenever you want an event sequence, I advise you to make the script as follows: if(Grid [x + 1, y].tag == "HYDROGEN" && Grid [x - 1, y].tag == "HYDROGEN" etc etc) by placing a logical AND, so that the script has the ability to only execute when all conditions are met. But once again I recall the lack of information in a way that can help you.

  • Good guys, I make the pieces fall without the physics of the engine. As you can see in the code above.

  • The whole basis of my game up to the moment was followed by this tutorial, https://www.youtube.com/watch?v=aurEgWxDfQQ&list=PLiRrp7UEG13axMHD7Kqdiy30c7ZBu_Zn7

1 answer

4


Before suggesting an algorithm to treat what you actually need, I’ll take the liberty of offering some tips that might help you to maybe even another future reader:

  1. Use comments. Your code has virtually no comment about what it does. Fine, it can be your style of programming. It just makes it harder for someone else to understand what you’ve produced. It even makes it difficult to maintain itself in the future, since it is common for us to forget the details of what we did after a long period without working on the project. You could comment on the methods, indicating what they serve or what they do, and at least on the attributes of the classes to indicate what they serve/are used for.

  2. Organize the code. Your code is also a bit messy. Again, each has its own style. But identation is not only for aesthetics: it facilitates reading and makes it easier to find where things are defined.

  3. Use Object Orientation well. The OO exists by an important principle: it facilitates reasoning about the problem. If you don’t follow it, you lose the advantage in using it. Okay, not everyone understands these concepts deeply, but it doesn’t hurt to study them, right? In your case, for example, you put behaviors that should be of the moving piece (which I think is the one of Tetrominó) in the class that controls the game. The verification behavior of forming molecules may seem to make more sense in the game class, but it is not the last moving Tetrominó that is able to form a molecule (After all, the others that are already stacked have not formed anything yet, because if they had, they would have already disappeared and become points, right?). An indicator that there are problems there is the fact that there’s code in the Tetrominó class that frequently invokes Game class methods (the method check, for example).

Well, on your solution, Mr @Soeiromass gave a cool tip. But assuming that you will not only have these two elements (hydrogen and carbon), this type of verification will become unviable. What I suggest is that you program, in the Tetrominó class, a list mechanism that keeps the neighboring elements (i.e., already connected). Thus, given any Tetrominó will be possible to consult of it (via a method call of type getNeighbours) which elements are already connected to it.

That list will be kept for each of the Tetrominós individually, from their "collision detection". To do this, add a Unity Researcher and define it as "Trigger" (since you don’t need the physics and do the translation manually). Then create the method OnTriggerEnter2D (I’m guessing your game is 2D) to capture the event in Tetrominó’s class. Note that each element will receive this event, since they all have their own colliders/triggers. So when A collides with B, A will add B to your list, and B will add A to your list.

Once you have this list and a method of accessing it, you can make the Game class receive an event (a warning via a method call actually serves) when the currently falling Tetrominó stop. He is the only one who matters from the point of view of the game, since only he is able to build a valid molecule (right? After all, if the others already positioned had valid molecules, they would have already been "treated" by the game). The game then prompts the neighbors list and compares it to a template. This template is for you to know if the neighbors' union forms something real (the Carbon molecule, for example), and can be kept in a configuration file read and accessed ideally by another specific class for this. There are several ways to implement this template and its comparison. One of them is to have a simple character sum. Assuming that each element has an identifier that is its letter (i.e. C, H, etc.), their combinations will also be simple count strings (i.e. CHHH or HCHH, etc.) In fact, this string with the letters can be what returns the query method to the neighbors, and it is even easier to compare with the template if when assembling this string the order of the letters is guaranteed alphabetical.

  • Luiz Vieira gives me your facebook to contact you

  • Carlos, if your goal is to ask punctual questions, I suggest using the [chat]. : ) Now, if you have other questions that may be useful to other people, open a new question. This site is not a forum, okay? If you haven’t done it yet, do the [tour].

  • I would like to use the chat, how to open the chat with you?

  • Luiz added the colliders to my objects and implemented the collision method in the Etromino class, now I’m doubtful in this list of neighbors and compare with a template. Do you have an example you can give me? Or help me implement this? I’m starting now in Unity and I don’t have much experience. Ever since I thank

  • Oi Carlos. Here are some tips to call someone for a chat: http://meta.pt.stackoverflow.com/a/2175/73 Only I had more suggested you try to find anyone Just to help you out on time. As you must have noticed by my delay, unfortunately I’m very busy today and I won’t be able to find much time to help you. :/

  • About lists/object arrays, do a tutorial. There is a lot available on the Internet. Type this: https://www.youtube.com/watch?v=-mee0meDDvE I also suggest the @Nils channel: https://www.youtube.com/watch?v=kzCRhK6x4KQ&list=PLa2bQ5uCFWA1RNqmaQIAWiq5HiWUGATyC

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.