Scrabble In Tetris Help Needed

Hey guys. I’m trying to make a game where Scrabble tiles fall down like Tetris tiles and when you make a word, it disappears like Tetris. I managed to make it with single letters but i cant figure out how to connect the letters together.

 void RegisterTile()
    {
        gameLogic.grid[Mathf.FloorToInt(gameObject.transform.position.x), Mathf.FloorToInt(gameObject.transform.position.y)] = gameObject.transform;
        TryWord();
    }

    bool CheckValid()
    {
        if(gameObject.transform.position.x > GameLogic.width ||
            gameObject.transform.position.x < 0 || 
            gameObject.transform.position.y < 0)
        {
            return false;
        }

        if (gameObject.transform.position.y < GameLogic.heigth && gameLogic.grid[Mathf.FloorToInt(gameObject.transform.position.x), Mathf.FloorToInt(gameObject.transform.position.y)] != null)
        {
            return false;
        }

        return true;
    }
    // Update is called once per frame
    void Update()
    {

        if(CheckValid())
        {
            check = true;
        }

        if (!fingerDown && Input.GetMouseButtonDown(0))
        {
            startPos = Input.mousePosition;
            fingerDown = true;
        }

        if (movable)
        {
            timer += 1 * Time.deltaTime;

            if (Input.GetKey(KeyCode.DownArrow) && timer > GameLogicNew.quickDropTime || fingerDown && timer > GameLogic.quickDropTime && Input.mousePosition.y < startPos.y - pixelDistToDetect)
            {
                gameObject.transform.position -= new Vector3(0, 2, 0);
                timer = 0;

                if (!CheckValid())
                {
                    movable = false;
                    gameObject.transform.position += new Vector3(0, 2, 0);
                    RegisterTile();
                    gameLogic.SpawnTile();
                }
            }
            else if (timer > GameLogicNew.dropTime)
            {
                gameObject.transform.position -= new Vector3(0, 2, 0);
                timer = 0;

                if (!CheckValid())
                {
                    movable = false;
                    gameObject.transform.position += new Vector3(0, 2, 0);
                    RegisterTile();
                    gameLogic.SpawnTile();
                }
            }

            if (Input.GetKeyDown(KeyCode.LeftArrow))
            {
                gameObject.transform.position -= new Vector3(2, 0, 0);

                if (!CheckValid())
                {
                    gameObject.transform.position += new Vector3(2, 0, 0);
                }
            }
            else if (Input.GetKeyDown(KeyCode.RightArrow))
            {
                gameObject.transform.position += new Vector3(2, 0, 0);

                if (!CheckValid())
                {
                    gameObject.transform.position -= new Vector3(2, 0, 0);
                }
            }

            if (fingerDown)
            {
                if (Input.mousePosition.x >= startPos.x + pixelDistToDetect) 
                {
                    gameObject.transform.position += new Vector3(2, 0, 0);
                    startPos = Input.mousePosition;
                    if (!CheckValid())
                    {
                        gameObject.transform.position -= new Vector3(2, 0, 0);
                    }
                }
                if (Input.mousePosition.x <= startPos.x - pixelDistToDetect)
                {
                    gameObject.transform.position -= new Vector3(2, 0, 0);
                    startPos = Input.mousePosition;
                    if (!CheckValid())
                    {
                        gameObject.transform.position += new Vector3(2, 0, 0);
                    }
                }
            }
        }
        if (fingerDown && Input.GetMouseButtonUp(0))
        {
            fingerDown = false;
        }
    }

    public void TryWord()
    {

            WordManager.currentWord += letterName.GetComponent<TMP_Text>().text;
            Debug.Log(letterName.GetComponent<TMP_Text>().text);
    }

it looks like this right now. When a letter hits the bottom, i can see it in the console but when multiple ones hit, i see them all together no matter where they are. I cant find a way to seperate them or show them in order (From left to right / from up to down). I couldnt find any tutorials on how to make a Scrabble game so i ask for your help. Thank you in advance.

I’d go about it this way:

Every time a block hits the bottom and sticks (the grid has changed), check for words on every block in the grid, Right and Down as far as it goes. But you need to have your wordlist indexed so that it does not become too expensive to check for words… GetComponent can certainly not be used as much.

Well, if it’s based around Scrabble squares and Tetris-style blocks falling into place, then once a tile has settled in place, the new state of your playfield should be a fixed/known state.

Right now, your block positioning appears to be based purely on physical positions in Unity. You should probably move away from that approach and use a pre-specified grid for placement, then reflect those positions back to your placement scheme instead.

With this in mind, you would have a fixed size for your playfield at any given time. Let’s say it’s 8x8 (to keep this example a bit smaller):

--------
--------
--------
--M--A--
--I--D-X
B-G--R-W
FDG-OECM
ZLE-TERQ

In this situation, you can easily store the current state of all the existing blocks in a 2-dimensional array, either as a char array or (preferably) a “Tile” array.

Each tile should contain information about the char associated with it, where that data is copied to the Text component. It’s much faster than reading strings from Text components themselves, and the playfield should be storing “Tile” information at all times.

Going back to my example above, the bottom row contains LE TER, where no complete word has been formed yet, but adding the letter ‘T’ in the middle would complete a new word.

Your playfield can simultaneously keep track of tiles that have changed. After all, the playfield wouldn’t be constantly shifting and changing; if a change is manually made, then you can limit your completed-word search to only use letters adjacent to ones that have been updated.

This means two things:

First: When a new letter is placed, check all tiles in its row and column (and diagonally, if applicable) for new words formed. If it’s feasible to do so without strings, it would almost definitely be the “faster” solution, but a string still works well enough once you’re limiting your search area.

// Example definition of playfield
Tile[,] playfield = new Tile[playfieldWidth, playfieldHeight];

// These are the array coordinates where the new Tile landed
int placedTileX;
int placedTileY;

// Markers to check word bounds
int firstCharX = placedTileX;
int lastCharX = placedTileX;
int firstCharY = placedTileY;
int lastCharY = placedTileY;

string wordCheckX = string.Empty;
string wordCheckY = string.Empty;
    
// Check backwards for the first letter in the word
for(int x = placedTileX - 1; x >= 0; x--)
{
	if(playfield[x, placedTileY] == null)
	{
		break;
	}
	else
	{
		firstCharX = x;
	}
}

// Check forwards for the last letter in the word
for(int x = placedTileX + 1; x < playfieldWidth; x++)
{
	if(playfield[x, placedTileY] == null)
	{
		break;
	}
	else
	{
		lastCharX = x;
	}
}

// Repeat the same basic principle for Y-axis

// ...

// Add char to your string to compare with dictionary
for(int x = firstCharX; x <= lastCharX; x++)
{
	wordCheckX += playfield[x, placedTileY].letter;
}

// Again, repeat for Y-axis

// Compare with dictionary (or ignore if below minimum letter count)

// After processing is complete...
for(int y = playfieldHeight - 1; y >= 0; y--)
{
	for(int x = playfieldWidth - 1; x >= 0; x--)
	{
		playfield[x, y].modified = false;
	}
}

Second: If you form a word, then by Tetris rules, the involved Tiles will disappear. All tiles above the formed word are moved down to the nearest available height. Then, this is why I mention marking all modified tiles… You’ll need to perform the same check as above for the entire range of tiles modified (not one-by-one, but as a group) to check every new row and column they are now adjacent to. On that note, it means my example would need to be changed to accommodate min/max X and Y axis ranges needing to be searched. That makes things a bit more involved, so it’s probably better to start simpler, then add more complex logic for searching for all words contained in arbitrary spaces simultaneously.