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

public class AtlasManager : MonoBehaviour
{
    public static AtlasManager instance;
    public SpriteAtlas blockAtlas;
    //싱글톤
    private void Awake()
    {
        //AtlasManager 클래스의 인스턴스를 instance에 할당
        instance = this;
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.U2D;
using Random = UnityEngine.Random;

public class Test : MonoBehaviour
{
    public Board board;
    private void Start()
    {
        board.CreateBoard();
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 1);
            RaycastHit2D raycastHit2D = Physics2D.Raycast(ray.origin, ray.direction);
            if (raycastHit2D.collider != null)
            {
                Block block = raycastHit2D.collider.GetComponent<Block>();
                Debug.Log($"[{block.row}, {block.col}] ({block.transform.position.x}, {block.transform.position.y}), {block.blockType}");
            }
        }
    }
}

 

using Codice.Client.BaseCommands.Filters;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class BlockSwapWindow : EditorWindow
{
    private int row1;
    private int col1;
    private int row2;
    private int col2;
    [MenuItem("Window/Block Swap Window")]
    
    public static void ShowWindow()
    {
        GetWindow<BlockSwapWindow>("Block Swap Window");
    }

    private void OnGUI()
    {
        GUILayout.Label("Swap Blocks", EditorStyles.boldLabel);

        row1 = EditorGUILayout.IntField("Row 1", row1);
        col1 = EditorGUILayout.IntField("Column 1", col1);
        row2 = EditorGUILayout.IntField("Row 2", row2);
        col2 = EditorGUILayout.IntField("Column 2", col2);

        //버튼 UI추가
        if (GUILayout.Button("Swap"))
        {
            Board.instance.SwapBlocks(row1, col1, row2, col2);
            Debug.Log($"Swapped blocks at [{row1}, {col1} ane [{row2}, {col2}]");
        }

    }

}

 

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

[CustomEditor(typeof(Block))]
public class BlockEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Block block = target as Block;
        if (GUILayout.Button("제거"))
        {
            Debug.Log($"[{block.row},{block.col}]을 제거 합니다.");

            Board.instance.RemoveBlock(block.row, block.col);
        }
    }

    
}

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    public int totalHeight = 10;
    public int height = 5;
    public int width = 9;
    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 2차원 배열 만들기
        board = new Block[totalHeight, width]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < height; i++) //board.GetLength(0)
        {
            for (int j = 0; j < width; j++) //board.GetLength(1)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[width]; //배열 초기화

        for (int i = 0; i < width; i++) //열
        {
            int existBlockCnt = 0;
            for (int j = 0; j < totalHeight; j++) //행
            {
                Block block = board[j, i];
                if (block != null)
                {
                    existBlockCnt++;

                }
            }
            int emptySpace = height - existBlockCnt;
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {
            for (int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];
                if (cnt > 0)
                {
                    Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
                    CreateBlockFromColumn(i, cnt);
                }
            }
        }
        arrEmptySpaceCol = null;
    }

    private void CreateBlockFromColumn(int col, int cnt)
    {
        int startRow = height; //행

        for (int i = 0; i < cnt; i++)
        {
            //[7, col] -> [8, col] -> [9, col]
            CreateBlock(startRow, col);
            startRow++;
        }
    }

    public void MoveAllBlocksInRow(int row)
    {
        if (row == 0)
        {
            Debug.Log("가장 아래 있는 행 입니다. (이동불가)");
            return;
        }

        int numberOfBlocksToMove = 0;

        for (int col = 0; col < width; col++)
        {
            int targetRow = row - 1;

            Block fromBlock = board[row, col];
            Block toBlock = board[targetRow, col];

            string strFromBlock = (fromBlock == null) ? "비어있음" : fromBlock.ToString();
            string strToBlock = (toBlock == null) ? "비어있음" : toBlock.ToString();



            if (fromBlock != null && toBlock == null)
            {
                //이동가능
                Debug.Log($"[{row},{col}] {strFromBlock} -> [{targetRow}, {col} {strToBlock}]으로 이동합니다");
                numberOfBlocksToMove++;
            }
            else
            {
                //이동 불가능
            }
        }
        if (numberOfBlocksToMove == 0)
        {
            Debug.Log($"{row} 행의 이동 블록이 업습니다.");
        }
        else
        {
            Debug.Log($"{row}행의 이동해야 할 블록이 {numberOfBlocksToMove}개 있습니다.");
        }
    }

    public void SwapBlocks(int row1, int col1, int row2, int col2)
    {
        if (board[row1, col1] == null && board[row2, col2] == null)
        {
            Debug.LogError($"[{row1}, {col1}]와 [{row2}, {col2}]가 모두 비어 있습니다. (스왑 실패)");
            return;
        }
        //위치 가져오기
        Vector2 fromPos = Block.Index2Position(row1, col1);
        Vector2 toPos = Block.Index2Position(row2, col2);

        //데이터 변경
        Block temp = board[row1, col1];
        board[row1, col1] = board[row2, col2];
        board[row2, col2] = temp;

        //비주얼 이동
        if (board[row1, col1] != null)
            board[row1, col1].SetPosition(fromPos);
        if (board[row2, col2] != null)
            board[row2, col2].SetPosition(toPos);

        Debug.Log($"Swapped blocks at [{row1}, {col1}] and [{row2}, {col2}]");

    }

}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    public int totalHeight = 10;
    public int height = 5;
    public int width = 9;
    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 2차원 배열 만들기
        board = new Block[totalHeight, width]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < height; i++) //board.GetLength(0)
        {
            for (int j = 0; j < width; j++) //board.GetLength(1)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[width]; //배열 초기화

        for (int i = 0; i < width; i++) //열
        {
            int existBlockCnt = 0;
            for (int j = 0; j < totalHeight; j++) //행
            {
                Block block = board[j, i];
                if (block != null)
                {
                    existBlockCnt++;

                }
            }
            int emptySpace = height - existBlockCnt;
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {
            for (int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];
                if (cnt > 0)
                {
                    Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
                    CreateBlockFromColumn(i, cnt);
                }
            }
        }
        arrEmptySpaceCol = null;
    }

    private void CreateBlockFromColumn(int col, int cnt)
    {
        int startRow = height; //행

        for (int i = 0; i < cnt; i++)
        {
            //[7, col] -> [8, col] -> [9, col]
            CreateBlock(startRow, col);
            startRow++;
        }
    }

    public void MoveAllBlocksInRow(int row)
    {
        if (row == 0)
        {
            Debug.Log("가장 아래 있는 행 입니다. (이동불가)");
            return;
        }

        int numberOfBlocksToMove = 0;

        for (int col = 0; col < width; col++)
        {
            int targetRow = row - 1;

            Block fromBlock = board[row, col];
            Block toBlock = board[targetRow, col];

            string strFromBlock = (fromBlock == null) ? "비어있음" : fromBlock.ToString();
            string strToBlock = (toBlock == null) ? "비어있음" : toBlock.ToString();



            if (fromBlock != null && toBlock == null)
            {
                //이동가능
                Debug.Log($"[{row},{col}] {strFromBlock} -> [{targetRow}, {col} {strToBlock}]으로 이동합니다");
                numberOfBlocksToMove++;
            }
            else
            {
                //이동 불가능
            }
        }
        if (numberOfBlocksToMove == 0)
        {
            Debug.Log($"{row} 행의 이동 블록이 업습니다.");
        }
        else
        {
            Debug.Log($"{row}행의 이동해야 할 블록이 {numberOfBlocksToMove}개 있습니다.");
        }
    }

    public void SwapBlocks(int row1, int col1, int row2, int col2)
    {
        if (board[row1, col1] == null && board[row2, col2] == null)
        {
            Debug.LogError($"[{row1}, {col1}]와 [{row2}, {col2}]가 모두 비어 있습니다. (스왑 실패)");
            return;
        }
        //위치 가져오기
        Vector2 fromPos = Block.Index2Position(row1, col1);
        Vector2 toPos = Block.Index2Position(row2, col2);

        //데이터 변경
        Block temp = board[row1, col1];
        board[row1, col1] = board[row2, col2];
        board[row2, col2] = temp;

        //비주얼 이동
        if (board[row1, col1] != null)
            board[row1, col1].SetPosition(fromPos);
        if (board[row2, col2] != null)
            board[row2, col2].SetPosition(toPos);

        Debug.Log($"Swapped blocks at [{row1}, {col1}] and [{row2}, {col2}]");

    }

}

 

using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEngine;

public class Block : MonoBehaviour
{
    public enum BlockType
    {
        Blue, Gray, Green, Pink, Yellow
    }

    public BlockType blockType;
    public SpriteRenderer spriteRenderer;
    public TMP_Text debugText;
    public int row;
    public int col;
    public void Init(BlockType blockType)
    {
        this.blockType = blockType;
        //이미지 변경 
        ChangeSprite(blockType);
    }

    public void ChangeSprite(BlockType blockType)
    {
        //블록의 이름을 넣어서 아틀라스에서 같은 이름인 sprite를 찾고 할당
        Sprite sp =
            AtlasManager.instance.blockAtlas.GetSprite(blockType.ToString());
        spriteRenderer.sprite = sp;
    }

    public void SetPosition(Vector2 pos)
    {
        transform.position = pos;
        var index = Position2Index(pos);
        row = index.row;
        col = index.col;
        debugText.text = $"[{index.row}, {index.col}]";
    }


    // 위치와 벡터 좌표가 다르기에 서로 교환가능하게 만들어주는 메소드
    public static (int row, int col) Position2Index(Vector2 pos)
    {
        return ((int)pos.y, (int)pos.x);
    }

    public static (int x, int y) Index2Position(Vector2 index)
    {
        return ((int)index.x, (int)index.y);
    }

    public static Vector2 Position2Index(int posX, int posY)
    {
        return new Vector2((int)posY, (int)posX);
    }

    public static Vector2 Index2Position(int row, int col)
    {
        return new Vector2((int)col, (int)row);
    }
}

아직 진행중

위에있는 줄을 아래로 내려야 한다.

그때 위의 줄은 row 이고 즉, 빈공간은 targetrow가 되는데

그 row에 해당하는 각각의 block이 fromBlock 과 toBlock으로 나뉜다.

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    private int currentRowIdx = 0;
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if(GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();
        }

        GUILayout.Space(5);

        if(GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }

        GUILayout.Space(5);
        if (GUILayout.Button("새로운 블록들 생성하기"))
        {
            board.CreateNewBlocks();
        }

        GUILayout.Space(5);
        if(GUILayout.Button($"현재 행 ({currentRowIdx}에 있는 모든 블록 내려보내기"))
        {
            Debug.Log($"{currentRowIdx}행에 있는 모든 블록을 내려 보냅니다.");
            currentRowIdx++;
            if(currentRowIdx > 9) /////////////////잘 봐야함
            {
                currentRowIdx = 0;
            }
        }
        
        if(GUILayout.Button("리셋 행"))
        {
            currentRowIdx = 0;
        }

        GUILayout.Space(5);
        if(GUILayout.Button("스왑 윈도우 열기"))
        {
            BlockSwapWindow.ShowWindow();
        }

    }


}

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    public int totalHeight = 10;
    public int height = 5;
    public int width = 9;
    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 2차원 배열 만들기
        board = new Block[totalHeight, width]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < height; i++) //board.GetLength(0)
        {
            for (int j = 0; j < width; j++) //board.GetLength(1)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[width]; //배열 초기화

        for (int i = 0; i < width; i++) //열
        {
            int existBlockCnt = 0;
            for (int j = 0; j < totalHeight; j++) //행
            {
                Block block = board[j, i];
                if (block != null)
                {
                    existBlockCnt++;

                }
            }
            int emptySpace = height - existBlockCnt;
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {
            for(int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];
                Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
                CreateBlockFromColumn(i, cnt);
            }
        }
        arrEmptySpaceCol = null;
    }

    private void CreateBlockFromColumn(int col, int cnt)
    {
        int startRow = height; //행

        for (int i = 0; i < cnt; i++)
        {
            //[7, col] -> [8, col] -> [9, col]
            CreateBlock(startRow, col);
            startRow++;
        }
    }

    public void MoveAllBlocksInRow(int row)
    {
        if (row == 0)
        {
            Debug.Log("가장 아래 있는 행 입니다. (이동불가)");
            return;
        }

        int numberOfBlocksToMove = 0;

        for (int col = 0; col < width; col++)
        {
            int targetRow = row - 1;

            Block fromBlock = board[row, col];
            Block toBlock = board[targetRow, col];

            string strFromBlock = (fromBlock == null) ? "비어있음" : fromBlock.ToString();
            string strToBlock = (toBlock == null) ? "비어있음" : toBlock.ToString();



            if (fromBlock != null && toBlock == null)
            {
                //이동가능
                Debug.Log($"[{row},{col}] {strFromBlock} -> [{targetRow}, {col} {strToBlock}]으로 이동합니다");
                numberOfBlocksToMove++;
            }
            else
            {
                //이동 불가능
            }
        }
            if(numberOfBlocksToMove == 0)
            {
                Debug.Log($"{row} 행의 이동 블록이 업습니다.");
            }
            else
            {
                Debug.Log($"{row}행의 이동해야 할 블록이 {numberOfBlocksToMove}개 있습니다.");
            }
    }

    public void SwapBlocks(int row1, int col1, int row2, int col2)
    {
        if (board[row1, col1] == null && board[row2, col2] == null)
        {
            Debug.LogError($"[{row1}, {col1}]와 [{row2}, {col2}]가 모두 비어 있습니다. (스왑 실패)");
            return;
        }
        //위치 가져오기
        Vector2 fromPos = Block.Index2Position(row1, col1);
        Vector2 toPos = Block.Index2Position(row2, col2);

        //데이터 변경
        Block temp = board[row1, col1];
        board[row1, col1] = board[row2,col2];
        board[row2, col2] = temp;

        //비주얼 이동
        if(board[row1, col1] != null)
            board[row1, col1].SetPosition(fromPos);
        if (board[row2, col2] != null)
            board[row2,col2].SetPosition(toPos);

        Debug.Log($"Swapped blocks at [{row1}, {col1}] and [{row2}, {col2}]");

    }

}

 

 

using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEngine;

public class Block : MonoBehaviour
{
    public enum BlockType
    {
        Blue, Gray, Green, Pink, Yellow
    }

    public BlockType blockType;
    public SpriteRenderer spriteRenderer;
    public TMP_Text debugText;
    public int row;
    public int col;
    public void Init(BlockType blockType)
    {
        this.blockType = blockType;
        //이미지 변경 
        ChangeSprite(blockType);
    }

    public void ChangeSprite(BlockType blockType)
    {
        //블록의 이름을 넣어서 아틀라스에서 같은 이름인 sprite를 찾고 할당
        Sprite sp =
            AtlasManager.instance.blockAtlas.GetSprite(blockType.ToString());
        spriteRenderer.sprite = sp;
    }

    public void SetPosition(Vector2 pos)
    {
        transform.position = pos;
        var index = Position2Index(pos);
        row = index.row;
        col = index.col;
        debugText.text = $"[{index.row}, {index.col}]";
    }

    public static (int row, int col) Position2Index(Vector2 pos)
    {
        return ((int)pos.y, (int)pos.x);
    }

    public static (int x, int y) Index2Position(Vector2 index)
    {
        return ((int)index.x, (int)index.y);
    }
    public static Vector2 Index2Position(int row, int col)
    {
        return new Vector2((int)col, (int)row);
    }
}
using System;

class Program
{
    static void Main(string[] args)
    {
        int a = 5;
        int b = 10;
        
        Console.WriteLine($"Before Swap: a = {a}, b = {b}");
        Swap(ref a, ref b);
        Console.WriteLine($"After Swap: a = {a}, b = {b}");
        
        string x = "hello";
        string y = "world";
        
        Console.WriteLine($"Before Swap: x = {x}, y = {y}");
        Swap(ref x, ref y);
        Console.WriteLine($"After Swap: x = {x}, y = {y}");
    }
    
    static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp;
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

 

https://docs.unity3d.com/ScriptReference/EditorWindow.html

 

Unity - Scripting API: EditorWindow

Create your own custom editor window that can float free or be docked as a tab, just like the native windows in the Unity interface. Editor windows are typically opened using a menu item.

docs.unity3d.com

 

 

 

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

public class BlockSwapWindow : EditorWindow
{
    [MenuItem("Window/Block Swap Window")]
    
    public static void ShowWindow()
    {
        GetWindow<BlockSwapWindow>("Block Swap Window");
    }

    private void OnGUI()
    {
        GUILayout.Label("Swap Blocks", EditorStyles.boldLabel);
    }
}

 

 

 

https://docs.unity3d.com/ScriptReference/GUILayout.Label.html

 

Unity - Scripting API: GUILayout.Label

Labels have no user interaction, do not catch mouse clicks and are always rendered in normal style. If you want to make a control that responds visually to user input, use a Box control Label in the Game View.

docs.unity3d.com

https://docs.unity3d.com/ScriptReference/EditorGUILayout.IntField.html

 

Unity - Scripting API: EditorGUILayout.IntField

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

 

 

 

using Codice.Client.BaseCommands.Filters;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class BlockSwapWindow : EditorWindow
{
    private int row1;
    private int col1;
    private int row2;
    private int col2;
    [MenuItem("Window/Block Swap Window")]
    
    public static void ShowWindow()
    {
        GetWindow<BlockSwapWindow>("Block Swap Window");
    }

    private void OnGUI()
    {
        GUILayout.Label("Swap Blocks", EditorStyles.boldLabel);

        row1 = EditorGUILayout.IntField("Row 1", row1);
        col1 = EditorGUILayout.IntField("Column 1", col1);
        row2 = EditorGUILayout.IntField("Row 2", row2);
        col2 = EditorGUILayout.IntField("Column 2", col2);
    }
}

 

 

using Codice.Client.BaseCommands.Filters;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;

public class BlockSwapWindow : EditorWindow
{
    private int row1;
    private int col1;
    private int row2;
    private int col2;
    [MenuItem("Window/Block Swap Window")]
    
    public static void ShowWindow()
    {
        GetWindow<BlockSwapWindow>("Block Swap Window");
    }

    private void OnGUI()
    {
        GUILayout.Label("Swap Blocks", EditorStyles.boldLabel);

        row1 = EditorGUILayout.IntField("Row 1", row1);
        col1 = EditorGUILayout.IntField("Column 1", col1);
        row2 = EditorGUILayout.IntField("Row 2", row2);
        col2 = EditorGUILayout.IntField("Column 2", col2);

        //버튼 UI추가
        if (GUILayout.Button("Swap"))
        {
            //Board.instance.SwapBlocks(row1, col1, row2, col2);
            Debug.Log($"Swapped blocks at [{row1}, {col1} ane [{row2}, {col2}]");
        }

    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    private int currentColIdx = 0;
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if(GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();
        }

        GUILayout.Space(5);

        if(GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }

        GUILayout.Space(5);
        if (GUILayout.Button("새로운 블록들 생성하기"))
        {
            board.CreateNewBlocks();
        }

        GUILayout.Space(5);
        if(GUILayout.Button($"현재 행 ({currentColIdx}에 있는 모든 블록 내려보내기"))
        {
            Debug.Log($"{currentColIdx}행에 있는 모든 블록을 내려 보냅니다.");
            currentColIdx++;
            if(currentColIdx > 9)
            {
                currentColIdx = 0;
            }
        }
        
        if(GUILayout.Button("리셋 행"))
        {
            currentColIdx = 0;
        }
    }

}

 

수정 후

 

public void FindEmptySpaceFromColumn()
{
    arrEmptySpaceCol = new int[width]; //배열 초기화

    for (int i = 0; i < width; i++) //열
    {
        int existBlockCnt = 0;
        for (int j = 0; j < totalHeight; j++) //행
        {
            Block block = board[j, i];
            if (block != null)
            {
                existBlockCnt++;

            }
        }
        int emptySpace = height - existBlockCnt;
        arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
        Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
    }

}

 

 

 

 

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if(GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();
        }

        GUILayout.Space(5);

        if(GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }

        GUILayout.Space(6);
        if (GUILayout.Button("새로운 블록들 생성하기"))
        {
            board.CreateNewBlocks();
        }
    }

}

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 1차원 배열 만들기
        board = new Block[5, 9]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < board.GetLength(0); i++)
        {
            for (int j = 0; j < board.GetLength(1); j++)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.GetLength(0); i++)    //행
        {
            for (int j = 0; j < board.GetLength(1); j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[board.GetLength(1)]; //배열 초기화

        for (int i = 0; i < board.GetLength(1); i++) //열
        {
            int emptySpace = 0;
            for (int j = 0; j < board.GetLength(0); j++) //행
            {
                Block block = board[j, i];
                if (block == null)
                {
                    emptySpace++;
                }
            }
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {

        }
    }

}

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 1차원 배열 만들기
        board = new Block[5, 9]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < board.GetLength(0); i++)
        {
            for (int j = 0; j < board.GetLength(1); j++)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.GetLength(0); i++)    //행
        {
            for (int j = 0; j < board.GetLength(1); j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[board.GetLength(1)]; //배열 초기화

        for (int i = 0; i < board.GetLength(1); i++) //열
        {
            int emptySpace = 0;
            for (int j = 0; j < board.GetLength(0); j++) //행
            {
                Block block = board[j, i];
                if (block == null)
                {
                    emptySpace++;
                }
            }
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {
            for(int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];
                Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
            }
        }
    }

}

 

 

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;

public class Board : MonoBehaviour
{
    public static Board instance;// 싱글톤
    private Block[,] board; //2차원 배열이 Block들을 관리
    public GameObject blockPrefab;
    private int[] arrEmptySpaceCol;

    public int totalHeight = 10;
    public int height = 5;
    public int width = 9;
    private void Awake()
    {
        instance = this;
    }

    public void CreateBoard()
    {
        //크기가 9인 BlockType의 2차원 배열 만들기
        board = new Block[totalHeight, width]; // 2차원 배열로 변경
        //5행 9열의 Block타입의 2차원 배열 만들기
        for (int i = 0; i < height; i++) //board.GetLength(0)
        {
            for (int j = 0; j < width; j++) //board.GetLength(1)
            {
                CreateBlock(i, j);
            }
        }
        PrintBoard();
    }

    public void CreateBlock(int row, int col)
    {
        Vector2 pos = new Vector2(col, row);
        Block.BlockType blockType = (Block.BlockType)Random.Range(0, 5);
        GameObject blockGo = Instantiate(blockPrefab);
        Block block = blockGo.GetComponent<Block>();
        block.Init(blockType);
        block.SetPosition(pos);

        //배열의 요소에 블록 넣기
        board[row, col] = block;
    }

    public void RemoveBlock(int row, int col)
    {
        Block block = board[row, col];
        Destroy(block.gameObject); //게임 오브젝트 파괴

        //배열의 요소를 비워줌
        board[row, col] = null;
    }

    public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < height; i++)    //행
        {
            for (int j = 0; j < width; j++)    //열
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                // 각 엘리먼트를 고정된 너비로 출력
                sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
            }
            sb.AppendLine();
        }
        Debug.Log(sb.ToString());
    }

    public void FindEmptySpaceFromColumn()
    {
        arrEmptySpaceCol = new int[width]; //배열 초기화

        for (int i = 0; i < width; i++) //열
        {
            int emptySpace = 0;
            for (int j = 0; j < height; j++) //행
            {
                Block block = board[j, i];
                if (block == null)
                {
                    emptySpace++;
                }
            }
            arrEmptySpaceCol[i] = emptySpace; // 배열의 인덱스(열)에 emptySpace(카운트)값 할당 => 각 열마다 빈공간의 개수
            Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
        }

    }

    public void CreateNewBlocks()
    {
        if (arrEmptySpaceCol == null || arrEmptySpaceCol.All(x => x == 0))
        {
            Debug.Log("빈 공간이 없습니다.");
        }
        else
        {
            for(int i = 0; i < arrEmptySpaceCol.Length; i++)
            {
                int cnt = arrEmptySpaceCol[i];
                Debug.Log($"{i}열에 {cnt}만큼 블록 생성 필요");
                CreateBlockFromColumn(i, cnt);
            }
        }
        arrEmptySpaceCol = null;
    }

    private void CreateBlockFromColumn(int col, int cnt)
    {
        int startRow = height; //행

        for (int i = 0; i < cnt; i++)
        {
            //[7, col] -> [8, col] -> [9, col]
            CreateBlock(startRow, col);
            startRow++;
        }
    }
}

 

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if(GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();
        }

        GUILayout.Space(5);

        if(GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }

        GUILayout.Space(5);
        if (GUILayout.Button("새로운 블록들 생성하기"))
        {
            board.CreateNewBlocks();
        }
    }

}

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.U2D;
using Random = UnityEngine.Random;

public class Test : MonoBehaviour
{
    public Board board;
    private void Start()
    {
        board.CreateBoard();
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 1);
            RaycastHit2D raycastHit2D = Physics2D.Raycast(ray.origin, ray.direction);
            if (raycastHit2D.collider != null)
            {
                Block block = raycastHit2D.collider.GetComponent<Block>();
                Debug.Log($"[{block.row}, {block.col}] ({block.transform.position.x}, {block.transform.position.y}), {block.blockType}");
            }
        }
    }
}

 

using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.Mathematics;
using UnityEngine;

public class Block : MonoBehaviour
{
    public enum BlockType
    {
        Blue, Gray, Green, Pink, Yellow
    }

    public BlockType blockType;
    public SpriteRenderer spriteRenderer;
    public TMP_Text debugText;
    public int row;
    public int col;
    public void Init(BlockType blockType)
    {
        this.blockType = blockType;
        //이미지 변경 
        ChangeSprite(blockType);
    }

    public void ChangeSprite(BlockType blockType)
    {
        //블록의 이름을 넣어서 아틀라스에서 같은 이름인 sprite를 찾고 할당
        Sprite sp =
            AtlasManager.instance.blockAtlas.GetSprite(blockType.ToString());
        spriteRenderer.sprite = sp;
    }

    public void SetPosition(Vector2 pos)
    {
        transform.position = pos;
        var index = Position2Index(pos);
        row = index.row;
        col = index.col;
        debugText.text = $"[{index.row}, {index.col}]";
    }

    public static (int row, int col) Position2Index(Vector2 pos)
    {
        return ((int)pos.y, (int)pos.x);
    }

    public static (int x, int y) Index2Position(Vector2 index)
    {
        return ((int)index.x, (int)index.y);
    }
}

 

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

public class AtlasManager : MonoBehaviour
{
    public static AtlasManager instance;
    public SpriteAtlas blockAtlas;
    //싱글톤
    private void Awake()
    {
        //AtlasManager 클래스의 인스턴스를 instance에 할당
        instance = this;
    }
}

 

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Board board = target as Board;

        if(GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();
        }

        GUILayout.Space(5);

        if(GUILayout.Button("각 열에 빈공간 찾기"))
        {
            board.FindEmptySpaceFromColumn();
        }
    }

}

 

 

public void FindEmptySpaceFromColumn()
{
    for(int i = 0; i <board.GetLength(1); i++)
    {
        int emptySpace = 0;
        for(int j = 0; j < board.GetLength(0); j++)
        {
            Block block = board[j, i];
            if(block == null)
            {
                emptySpace++;
            }
        }
        Debug.Log($"{i}열의 빈공간은 {emptySpace}개 입니다.");
    }

}
public void PrintBoard()
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < board.GetLength(0); i++)    //행
    {
        for (int j = 0; j < board.GetLength(1); j++)    //열
        {
            Block block = board[i, j];
            string strElement = (block == null) ? "null" : block.blockType.ToString();
            // 각 엘리먼트를 고정된 너비로 출력
            sb.AppendFormat("[{0},{1}] = {2,-11}", i, j, strElement);
        }
        sb.AppendLine();
    }
    Debug.Log(sb.ToString());
}

 

완벽히 원하는 간격은 아니였으나 계속 물은 끝에 이 정도의 결과를 얻음

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

[CustomEditor(typeof(Block))]
public class BlockEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        Block block = target as Block;
        if (GUILayout.Button("제거"))
        {
            Debug.Log($"[{block.row},{block.col}]을 제거 합니다.");
        }
    }
}

 

https://docs.unity3d.com/ScriptReference/Editor.OnInspectorGUI.html

 

Unity - Scripting API: Editor.OnInspectorGUI

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

 

 

  • OnInspectorGUI 메서드는 Unity의 Inspector에서 해당 컴포넌트(Block)의 GUI를 그리는 메서드
  • base.OnInspectorGUI()는 기본적으로 해당 컴포넌트의 Inspector를 그리는 기능을 수행

 

 

 

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

[CustomEditor(typeof(Board))]
public class BoardEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        
        Board board = target as Board;

        if (GUILayout.Button("배열 요소 출력"))
        {
            board.PrintBoard();;
        }
    }
}

 

 

public void PrintBoard()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < board.GetLength(0); i++)    //행
        {
            for (int j = 0; j < board.GetLength(1); j++)    //열 
            {
                Block block = board[i, j];
                string strElement = (block == null) ? "null" : block.blockType.ToString();
                sb.Append($"[{i},{j}] = {strElement}  ");
            }
            sb.AppendLine();
        }
        Debug.Log(sb);
    }

 

카메라의 Transform과 Size를 조절하여

원하는 곳에 위치시키기

+ Recent posts