1. Block Movement and Rotation

Each Tetromino (Tetris piece) is controlled by player input and reacts to game events like collisions.

using UnityEngine;

public class Tetromino : MonoBehaviour
{
    private float fallTime = 1.0f; // Time for each block to fall
    private float fallTimer;

    void Update()
    {
        HandleInput();
        HandleFall();
    }

    private void HandleInput()
    {
        if (Input.GetKeyDown(KeyCode.LeftArrow))
            Move(Vector3.left);

        if (Input.GetKeyDown(KeyCode.RightArrow))
            Move(Vector3.right);

        if (Input.GetKeyDown(KeyCode.UpArrow))
            Rotate();

        if (Input.GetKeyDown(KeyCode.DownArrow))
            Move(Vector3.down);
    }

    private void HandleFall()
    {
        fallTimer += Time.deltaTime;
        if (fallTimer >= fallTime)
        {
            Move(Vector3.down);
            fallTimer = 0;
        }
    }

    private void Move(Vector3 direction)
    {
        transform.position += direction;

        if (!IsValidPosition())
            transform.position -= direction; // Revert if invalid
    }

    private void Rotate()
    {
        transform.Rotate(0, 0, -90);

        if (!IsValidPosition())
            transform.Rotate(0, 0, 90); // Revert if invalid
    }

    private bool IsValidPosition()
    {
        foreach (Transform child in transform)
        {
            Vector2 pos = RoundVector(child.position);
            if (!GridManager.IsInsideGrid(pos) || GridManager.IsOccupied(pos))
                return false;
        }
        return true;
    }

    private Vector2 RoundVector(Vector2 vector)
    {
        return new Vector2(Mathf.Round(vector.x), Mathf.Round(vector.y));
    }

    private void OnCollision()
    {
        GridManager.AddToGrid(this);
        GameManager.Instance.SpawnNewBlock();
        enabled = false; // Disable script on collision
    }
}

2. Grid Management

The grid tracks the position of blocks, manages row clearing, and handles collision detection.

using UnityEngine;

public class GridManager : MonoBehaviour
{
    public static int width = 10;
    public static int height = 20;

    private static Transform[,] grid = new Transform[width, height];

    public static bool IsInsideGrid(Vector2 position)
    {
        return position.x >= 0 && position.x < width && position.y >= 0;
    }

    public static bool IsOccupied(Vector2 position)
    {
        return grid[(int)position.x, (int)position.y] != null;
    }

    public static void AddToGrid(Tetromino block)
    {
        foreach (Transform child in block.transform)
        {
            Vector2 pos = RoundVector(child.position);
            grid[(int)pos.x, (int)pos.y] = child;
        }

        CheckForCompleteRows();
    }

    public static void CheckForCompleteRows()
    {
        for (int y = 0; y < height; y++)
        {
            if (IsRowComplete(y))
            {
                ClearRow(y);
                MoveRowsDown(y);
                y--; // Recheck the same row after moving
            }
        }
    }

    private static bool IsRowComplete(int y)
    {
        for (int x = 0; x < width; x++)
        {
            if (grid[x, y] == null)
                return false;
        }
        return true;
    }

    private static void ClearRow(int y)
    {
        for (int x = 0; x < width; x++)
        {
            Destroy(grid[x, y].gameObject);
            grid[x, y] = null;
        }
    }

    private static void MoveRowsDown(int clearedRow)
    {
        for (int y = clearedRow + 1; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                if (grid[x, y] != null)
                {
                    grid[x, y - 1] = grid[x, y];
                    grid[x, y] = null;
                    grid[x, y - 1].position += Vector3.down;
                }
            }
        }
    }

    private static Vector2 RoundVector(Vector2 vector)
    {
        return new Vector2(Mathf.Round(vector.x), Mathf.Round(vector.y));
    }
}

3. Game Manager

The game manager initializes the game, spawns Tetrominoes, and handles scoring and game over logic.

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public GameObject[] tetrominoPrefabs;
    public Transform spawnPoint;
    public int score = 0;

    private void Awake()
    {
        if (Instance == null)
            Instance = this;
        else
            Destroy(gameObject);
    }

    private void Start()
    {
        SpawnNewBlock();
    }

    public void SpawnNewBlock()
    {
        int randomIndex = Random.Range(0, tetrominoPrefabs.Length);
        Instantiate(tetrominoPrefabs[randomIndex], spawnPoint.position, Quaternion.identity);
    }

    public void AddScore(int linesCleared)
    {
        int points = 100 * linesCleared;
        score += points;
        Debug.Log("Score: " + score);
    }

    public void CheckGameOver()
    {
        for (int x = 0; x < GridManager.width; x++)
        {
            if (GridManager.IsOccupied(new Vector2(x, GridManager.height - 1)))
            {
                Debug.Log("Game Over!");
                Time.timeScale = 0; // Pause the game
                break;
            }
        }
    }
}

Additional Setup

  1. Create Prefabs for Tetrominoes:
    • Design the 7 standard Tetromino shapes (I, O, T, S, Z, L, J) as prefabs using Unity’s editor.
    • Attach the Tetromino script to each prefab.
  2. Grid and Spawner Setup:
    • Add the GridManager script to an empty GameObject in the scene.
    • Add the GameManager script to another GameObject and set the tetrominoPrefabs array and spawnPoint.
  3. Scene Hierarchy:
    • Ensure you have a clean hierarchy with properly assigned scripts and prefabs.

Features Included in This Implementation

  1. Block Movement and Rotation: Smooth and collision-aware.
  2. Row Clearing: Fully functional with dynamic row adjustments.
  3. Random Block Spawning: Randomized yet modular for reuse.
  4. Scoring: Reward players for clearing lines.
  5. Game Over Detection: Ensures game ends when blocks overflow.

By following this guide, you can create a functional Tetris game in Unity that is highly modular and extensible!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다