하참이의 아이디어노트

유니티로 2D 체스 만들기 (4) 본문

Unity/Unity Chess

유니티로 2D 체스 만들기 (4)

하참이 2024. 3. 18. 17:00

https://www.youtube.com/watch?v=f3wOIJRlg40&list=PLXV-vjyZiT4b7WGjgiqMy422AVyMaigl1&index=5

 

글 작성에 앞서 이 주제에 관련된 글들은 전부 위 영상을 참고해서 제작한 점을 미리 밝힙니다.

 


 

 

 

 

 

지난시간엔 체스말 프리팹들을 시작시 배치하는 기능을 게임메니저에 구현하였습니다. 이번시간에는 체스말을 클릭하면 움직이도록 하는 moveplate를 생성해보도록 하겠습니다.

 

 

 

우선 체스 말이 움직이는 방식을 어떻게 구현할 지를 생각해야합니다. 저희가 구현할 방식은 다음과 같습니다.

 

 

 

1. 움직이고 싶은 체스말을 클릭하면 움직일 수 있는 이동경로를 계산, 표시합니다.

2. 해당 이동경로를 클릭하면 말이 움직입니다. 체스말 프리팹 Chessman 코드의 위치 속성(xBaord, yBoard)과 게임매니저 Game 코드의 위치 속성(positions, playerBlack, playerWhite)등을 수정해야 합니다.

3. 차례를 상대에게 넘겨 줍니다.

 

 

 

 

 

 

그렇다면 체스말이 이동하려면 '이동할 수 있는 구간'을 계산해야겠지요. 다음 메소드를 Game.cs 스크립트에 추가합니다.

 

 

    public void SetPositionEmpty(int x, int y)
    {
        positions[x, y] = null;
    }

    public  GameObject GetPosition(int x, int y)
    {
        return positions[x, y];
    }

    public bool PositionOnBoard(int x, int y)
    {
        if (x < 0 || y < 0 || x >= positions.GetLength(0) || y >= positions.GetLength(1)) return false;
        return true;
    }

 

 

 

 

 

 

 

코드에  대한 설명은 다음과 같습니다.

SetPositionEmpty(int x, int y) 메소드는 체스 말이 이동했을 때 자리를 비우기 위한 메소드 입니다.

GetPosition(int x, int y) 메소드는 포지션을 입력하면 해당 포지션의 체스말 오브젝트를 반환합니다.

PositionOnBoard(int x, int y) 메소드는 포지션이 체스보드 위에 있는지를 나타내는 유틸리티 메소드입니다. 움직일 수 있는 반경을 제한하는 계산은 게임제작시에 자주 사용할 기능이기 때문에 미리 구현해둡니다.

 

 

 

 

 

 

다음은 체스 말을 클릭하면 움직일 경로를 나타내기 위한 moveplate를 만들겠습니다. 다음 경로에서 moveplate 스프라이트를 다운받습니다.

 

https://github.com/etredal/Chess_App/blob/master/TUTORIAL/MovePlate.png

 

 

다운받고 유니티 에셋에 임포트가 끝났다면 moveplate의 스프라이트의 필터모드 역시 제거하겠습니다. 제거후에 Apply로 변경사항을 저장하는 것을 잊지 맙시다.

 

 

 

 

 

 

 

 

다음은 moveplate을 프리팹화 시키겠습니다. moveplate를 Scene 또는 Hierachy로 드래그 하여 오브젝트를 생성한 뒤, Scale을 (3.5, 3.5, 1)로 변경합니다.

 

 

 

 

 

 

 

 

 

 

moveplate를 프리팹화 하기 위하여 생성했던 오브젝트를 다시 Object 폴더로 드래그합니다. 후에 MovePlate 오브젝트를 삭제합니다.

 

 

 

 

 

 

 

 

 

다음은 moveplate를 다루기 위한 스크립트를 생성해주겠습니다. Scripts 폴더에 MovePlate.cs 스크립트를 생성합니다.

 

 

 

 

 

 

 

MovePlate.cs의 스크립트를 다음과 같이 작성합니다. 작성이 완료되면 DestroyMovePlate() 메소드가 없기 때문에 오류가 발생할 것입니다.

 

 

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

public class MovePlate : MonoBehaviour
{
    public GameObject controller;

    GameObject reference = null;

    // Board positions, not wolrd positions
    int matrixX;
    int matrixY;

    // flase: movement, true: attacking
    public bool attack = false;

    public void Start()
    {
        if (attack)
        {
            // Change to red
            gameObject.GetComponent<SpriteRenderer>().color = new Color(1.0f, 0.0f, 0.0f, 1.0f);
        }
    }

    public void OnMouseUp()
    {
        controller = GameObject.FindGameObjectWithTag("GameController");

        if (attack)
        {
            GameObject cp = controller.GetComponent<Game>().GetPosition(matrixX, matrixY);

            Destroy(cp);
        }

        controller.GetComponent<Game>().SetPositionEmpty(reference.GetComponent<Chessman>().GetXBoard(), reference.GetComponent<Chessman>().GetYBoard());

        reference.GetComponent<Chessman>().SetXBoard(matrixX);
        reference.GetComponent<Chessman>().SetYBoard(matrixY);
        reference.GetComponent<Chessman>().SetCoords();

        controller.GetComponent<Game>().SetPosition(reference);

        reference.GetComponent<Chessman>().DestroyMovePlates();
    }

    public void SetCoords(int x, int y)
    {
        matrixX = x;
        matrixY = y;
    }

    public void SetReference(GameObject obj)
    {
        reference = obj;
    }

    public GameObject GetReference()
    {
        return reference;
    }
}

 

 

다음은 코드에 대한 설명입니다. 코드를 작성할 때 해당 설명에 맞는 코드 위치에 주석처리하여 공부하는 것을  추천드립니다.

 

controller는 게임컨트롤러와 상호작용하기 위한 게임오브젝트 필드입니다.

reference는 이 코드가 할당된 moveplate가 어떤 체스말의 이동경로를 나타내는지를 참조하기위한 변수입니다.

matrixX, matrixY는 해당 moveplate의 체스보드상의 좌표를 나타내기 위한 변수입니다.

attack은 해당 이동경로에 공격이 가능한 말인지를 구분하기 위한 부울 자료형입니다.

 

Start()는 오브젝트가 생성되면 실앻되는 메소드입니다. 만약 해당 위치가 공격 가능한 위치일 경우 moveplate의 색상을 붉게 만듭니다. 

 

OnMouseUp()은 MonoBehaviour에서 제공하는 메소드로 오브젝트가 클릭되었을 경우 실행되는 메소드입니다. 이동경로를 나타낸 moveplate를 클릭하면 체스 말이 이동을 해야겠지요.

GameController를 찾아 controller 변수에 할당합니다. (해당사항은 싱글턴패턴을 적용하는 것이 좋습니다..만 간단한 게임의 구현임으로 이렇게 한 것으로 보입니다.)

만일 공격 가능한 위치의 경우 해당 위치의 상대 체스말을 제거합니다.

공격 가능하지 않던 공격을 한 후에 상대 체스말을 제거한 후 이던, 체스말을 이동시킵니다. reference의 체스 말의 원래 위치를 SetPositionEmpty() 메서드를 사용해서 비우고 클릭 된 moveplate의 위치로 체스말의 위치 속성을 변경합니다. 그렇게 변한 위치로 체스말 오브젝트의 실제 위치까지 변경합니다.

마지막으로 생성되어있던 moveplate들을 제거합니다.

 

SetCoords(int x, int y)는 moveplate의 좌표를 입력하기 위한 메소드입니다. 

SetReference(GameObject obj)는 moveplate가 어떤 체스말의 이동경로를 나타내는지를 참조하는 reference 변수를 입력하기 위한 메소드 입니다.

위 두 메소드는 moveplate를 생성할 때 주로 사용할 것 입니다.

GetReference()는 다른 코드로 reference를 반환하기 위해 사용하는 메소드입니다.

 

 

 

 

 

 

작성한 MovePlate.cs 코드를 MovePlate 프리팹에 컴포턴트로 추가합니다.

 

 

 

 

 

 

 

많은 코드를 작성하고 이해하였지만 아직은 불완전합니다. DestroyMovePlates() 메소드도 구현되지 않아 실행조차 되지 않구요. 급하신 분들은 바로 다음 글로 넘어가셔서 구현을 계속하시는것도 좋고 천천히 배우고 싶으신 분들은 위 개념을 한번 더 정리하는 것을 추천 드립니다.

 

긴 글 읽어주셔서 감사합니다!!