Unity에서 3-Match 퍼즐 그리드생성 코드 업데이트

안녕하세요! 이번에는 Unity에서 3-Match Grid 생성코드 업데이트 된 버전입니다.

Grid Manager 클래스 소개

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridManager : MonoBehaviour
{
    public int _gridHeight = 6;
    public int _gridWidth = 6;
    public GameObject grid1Sprite;
    public GameObject grid2Sprite;
    private int currentRowType = 1;
    [SerializeField] private int _maxRows = 9;
    [SerializeField] private SpawnManager spawnManager;
    [SerializeField] private CharacterManager characterManager;

    private void Start()
    {
        GenerateInitialGrid();
        spawnManager.SpawnCharacters();
    }

    public void GenerateInitialGrid()
    {
        for (int y = 0; y < _gridHeight; y++)
        {
            for (int x = 0; x < _gridWidth; x++)
            {
                GameObject spritePrefab = (x + y) % 2 == 0 
                ? grid1Sprite 
                : grid2Sprite;
                GameObject cell = 
                Instantiate(spritePrefab, new Vector3(x, y, 0), 
                Quaternion.identity, transform);
                if (!spawnManager.IsCharacterAtPosition(new Vector3(x, y, 0)))
                {
                    int randomCharacterIndex = Random.Range(0, 
                    characterManager.characterGroup.Count);
                    spawnManager.SpawnCharacterAtPosition
                    (randomCharacterIndex, x, y);
                }
            }
        }
    }


    public void AddRow()
    {
        if (_gridHeight < _maxRows)
        {
            _gridHeight++;

            // Move existing characters up
            foreach (GameObject character in spawnManager.GetPooledCharacters())
            {
                if (character.activeInHierarchy)
                {
                    Vector3 newPosition = character.transform.position;
                    newPosition.y += 1;
                    character.transform.position = newPosition;
                }
            }

            // Create new row and spawn characters
            for (int x = 0; x < _gridWidth; x++)
            {
                GameObject spritePrefab = (x + currentRowType) % 2 == 0 
                ? grid1Sprite 
                : grid2Sprite;
                Instantiate(spritePrefab, new Vector3(x, -1, 0), 
                Quaternion.identity, transform);
                if (!spawnManager.IsCharacterAtPosition(new Vector3(x, -1, 0)))
                {
                    int randomCharacterIndex = 
                    Random.Range(0, characterManager.characterGroup.Count);
                    spawnManager.SpawnCharacterAtPosition
                    (randomCharacterIndex, x, -1);
                }
            }

            // Move the entire grid up
            foreach (Transform child in transform)
            {
                Vector3 newPosition = child.position;
                newPosition.y += 1;
                child.position = newPosition;
            }
            currentRowType = currentRowType == 1 
            ? 2 
            : 1;
            spawnManager.DeactivateCharactersOutsideGrid
            (_gridWidth, _gridHeight);
        }
    }
}

저번과 달라진 점은 기존에는 Grid Manager에서 케릭터의 스폰관리를 함께 했다면, 이번에는 코드를 분리하여 케릭터 소환을 목적으로 하는 클래스를 새로 생성하였습니다.

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SpawnManager : MonoBehaviour
{
    [SerializeField]
    private CharacterManager characterManager;
    [SerializeField]
    private GridManager gridManager;
    [SerializeField]
    private CharacterPool characterPool;

    private int[] objectCounts = new int[5];

    public void SpawnCharacters()
    {
        List<Vector2Int> availablePositions = new List<Vector2Int>();

        for (int x = 0; x < gridManager._gridWidth; x++)
        {
            for (int y = 0; y < gridManager._gridHeight; y++)
            {
                availablePositions.Add(new Vector2Int(x, y));
            }
        }

        int[] targetCounts = { 7, 7, 7, 7, 8 };

        int[] currentCounts = new int[5];

        while (availablePositions.Count > 0 && currentCounts.Sum() < 36)
        {
            int randomCharacterIndex = 
            Random.Range(0, characterManager.characterGroup.Count);
            if (currentCounts[randomCharacterIndex] < 
            targetCounts[randomCharacterIndex])
            {
                int randomPositionIndex = 
                Random.Range(0, availablePositions.Count);
                Vector2Int randomPosition = 
                availablePositions[randomPositionIndex];
                availablePositions.RemoveAt(randomPositionIndex);
                SpawnCharacterAtPosition(randomCharacterIndex, 
                randomPosition.x, randomPosition.y);
                currentCounts[randomCharacterIndex]++;
            }
        }
    }

    public void SpawnCharacterAtPosition(int characterIndex, int x, int y)
    {
        Vector3 spawnPosition = new Vector3(x, y, 0);
        if (!IsCharacterAtPosition(spawnPosition))
        {
            GameObject characterPrefab = 
            characterManager.characterGroup[characterIndex].gameObject;
            GameObject pooledCharacter = characterPool.GetPooledCharacter();
            if (pooledCharacter != null)
            {
                pooledCharacter.GetComponent<CharacterBase>().
                Setup(characterPrefab.GetComponent<CharacterBase>());
                pooledCharacter.transform.position = spawnPosition;
                pooledCharacter.SetActive(true);
            }
        }
    }


    public List<GameObject> GetPooledCharacters()
    {
        return characterPool.GetPooledCharacters();
    }


    public bool IsCharacterAtPosition(Vector3 position)
    {
        foreach (GameObject character in characterPool.GetPooledCharacters())
        {
            if (character.activeInHierarchy 
            && character.transform.position == position)
            {
                return true;
            }
        }
        return false;
    }


    public void DeactivateCharactersOutsideGrid(int gridWidth, int gridHeight)
    {
        foreach (GameObject character in characterPool.GetPooledCharacters())
        {
            if (character.activeInHierarchy)
            {
                Vector3 position = character.transform.position;
                if (position.x < 0 
                || position.x >= gridWidth 
                || position.y < 0 
                || position.y >= gridHeight)
                {
                    character.SetActive(false);
                }
            }
        }
    }
}

하지만, 케릭터의 위치가 바뀌어야 하지만 그 뒤의 Grid가 바뀌는 버그,,,