Unity/3Match

[Unity] 3) Input / 블럭 Swap

GiveZero 2023. 2. 19. 22:11

유니티에는 다음과 같이 Event Trigger이 존재하는데, 컴포넌트로 사용하지않고

 

스크립트 내에서 설정할 것이다.

 

BlockController.cs

    void InitEventTrigger()
    {
        EventTrigger eventTrigger = transform.GetComponent<EventTrigger>();

        EventTrigger.Entry pointerDown = new EventTrigger.Entry();
        pointerDown.eventID = EventTriggerType.PointerDown;
        pointerDown.callback.AddListener((data) => { OnPointerDown((PointerEventData)data); });
        eventTrigger.triggers.Add(pointerDown);

        EventTrigger.Entry pointerUp = new EventTrigger.Entry();
        pointerUp.eventID = EventTriggerType.PointerUp;
        pointerUp.callback.AddListener((data) => { OnPointerUp((PointerEventData)data); });
        eventTrigger.triggers.Add(pointerUp);

        EventTrigger.Entry pointerEnter = new EventTrigger.Entry();
        pointerEnter.eventID = EventTriggerType.PointerEnter;
        pointerEnter.callback.AddListener((data) => { OnPointerEnter((PointerEventData)data); });
        eventTrigger.triggers.Add(pointerEnter);
    }

    void OnPointerDown(PointerEventData data)
    {
        boardController.SelectBlock(this);
    }

    void OnPointerUp(PointerEventData data)
    {
        boardController.UnSelectBlock(this);
    }

    void OnPointerEnter(PointerEventData data)
    {
        boardController.PointBlock(this);
    }
    #endregion

다음과 같이 EventTrigger을 만들어 사용할 수 있다.

 

 

BoardController.cs

    #region Input
    public void SelectBlock(BlockController block)
    {
        if (!canSelect)
            return;

        //Debug.Log(block.info.X + " , " + block.info.Y + " , "+ block.info.colorType.ToString() + block.info.blockType.ToString() + block.info.pieceType.ToString() + " Select!");
        //Debug.Log(board._blocks[block.info.index].info.X + " , " + board._blocks[block.info.index].info.Y + " Select!");
        
        canSelect = false;
        selectedBlock = block;
        canSwap = true;
    }

    public void UnSelectBlock(BlockController block)
    {
        if (canSelect)
            return;

        canSelect = true;
        //Debug.Log(block.info.X + "," + block.info.Y + "UnSelect!");
    }

    public void PointBlock(BlockController block)
    {
        if (selectedBlock == null || !canSwap || canSelect || block.info.blockType == BlockType.EMPTY || block.info.blockType == BlockType.NEVER)
            return;

        //Debug.Log(block.info.X + "," + block.info.Y + "Point Select!");

        for (int i = 0; i < 4; i++)
        {
            int x = selectedBlock.info.X + dx[i];
            int y = selectedBlock.info.Y + dy[i];

            if(block.info.X == x && block.info.Y == y)
            {
                canSwap = false;
                canSelect = false;
                targetBlock = block;
                StartCoroutine(SwapBlock());
                break;
            }
        }
    }
    #endregion

SelectBlock은 처음 선택한 블럭이고, PointBlock은 selectBlock이 존재할 때, 주변 4방향의 블럭으로 포인트를 갖다댈 시 발생하는 함수이다.

 

마우스 클릭 - selectedBlock

마우스 드래그 - targetBlock

 

Swap

BoardController.cs

교체할 수 있는지 없는지 검사

InitBoardMatch(BFSMode.Match) 은 너무 길기 때문에 다음 포스트에 다시 정리

-> 매치할 수 있는것이 있는지 탐색하기 위한 함수

 

SortBoard -> Block의 x,y값을 계산하여 자동으로 배열 내 순서를 변경

 

ChangeBlockValue -> 두 Block의 값을 변경하고 위치를 변경함

    IEnumerator SwapBlock()
    {
        //Debug.Log("Swap Start");
        CanMove--;
        ChangeBlockValue(selectedBlock, targetBlock);

        if (InitBoardMatch(BFSMode.Match))
        {
            while (isCoroutineAcitve)
                yield return null;
            targetBlock = null;
            selectedBlock = null;
            StartCoroutine(BlockDownAndRespawn());
        }
        else
        {
            CanMove++;
            while (isCoroutineAcitve)
                yield return null;
            ChangeBlockValue(selectedBlock, targetBlock);
            canSwap = true;
            canSelect = true;
        }
        Managers.UI.FindPopup<UI_BoardPopup>().RefreshUI();
    }

    private void SortBoard()
    {
        Array.Sort(board._blocks, delegate(BlockController b1, BlockController b2)
        {
            return b1.info.index.CompareTo(b2.info.index);
        });
    }

    void ChangeBlockValue(BlockController A, BlockController B, bool DirectMove = false, float speed = 1)
    {
        Vector3 APos = board._cells[A.info.X, A.info.Y].transform.position;
        Vector3 BPos = board._cells[B.info.X, B.info.Y].transform.position;

        Block temp = new Block(A.info);

        StartCoroutine(A.MoveToTarget(BPos, B.info, speed));
        if (DirectMove)
            B.MoveToTargetDirect(APos, temp);
        else
            StartCoroutine(B.MoveToTarget(APos, temp, speed));

        SortBoard();

    }

 

BlockController.cs

    public IEnumerator MoveToTarget(Vector3 Target, Block other, float speed = 2)
    {
        BoardController.isCoroutineAcitve = true;

        info.X = other.X;
        info.Y = other.Y;
        while ((Target - transform.position).sqrMagnitude > 0.001f)
        {
            transform.position = Vector3.MoveTowards(transform.position, Target, speed * 500 * Time.deltaTime);
            yield return null;
        }
        transform.position = Target;
        BoardController.isCoroutineAcitve = false;
    }