오늘은 Balatro 모작 최종 개발에 따른 내용정리를 비롯하여 프로젝트에 대한 회고를 작성하도록 하겠습니다.
개발 기간: 26. 4. 8 ~ 26. 4. 27
개발 환경 Unity(6000.3.9f1), C#
주요 라이브러리: DOTween(애니메이션)
핵심 구현 목표
1. 카드 생성, 셔플 & 드로우(Fisher-Yates)
2. 포커 족보 판정 엔진 구현
3. 순차 점수 계산 및 조커 카드 효과 시스템
4. 씬 간 데이터 유지 및 상점 시스템
5. 포커 족보, 게임 내 자원 강화 시스템
모든 카드의 공통 속성을 규격화하여 유지보수성과 확장성을 고려했습니다.
조커 카드의 개별 인스턴스와 분리한 후, 전역적으로 접근 가능한 정적클래스로 연산 규칙을 통합 관리했습니다.
Array : 드로우 핸드, 슬롯
고정된 크기의 사용 및 인덱스 기반의 UI 동기화가 이루어져 사용
List: 덱, 버린카드 저장
데이터의 가변 빈도 고려 및 셔플 알고리즘 구현 고려
삭제, 추가로 인한 크기 변화의 유연한 관리를 위해 사용
Queue: 조커 효과 계산
Balatro의 조커 카드 계산 매커니즘은 슬롯에 배치된 순서를 기준으로 순차적으로 계산되는 것을 고려하여 Queue를 활용하여 순차적으로 호출
Dictionary: 족보 플레이 횟수 기록, 족보 강화 레벨관리
Dictionary<HandRanking, int>를 통해 Key를 통한 빠른 조회처리
씬 전환, 사운드 관리, 게임 내 정보 관리를 싱글톤으로 설계하여 씬 전환 시에도 데이터 정합성을 유지하였습니다.
점수 계산의 경우 다음과 같이 진행됨
Issue
InGameScene에 배치한 싱글톤 RoundManager가 씬 전환시 파괴됨
Process
싱글톤이 씬전환에도 유지되도록 하는 코드 DontDestroyOnLoad가 구현되지 않았는지 확인했지만 정상 구현됨
모든 씬에 동일한 싱글톤을 배치해보았으나 여전히 파괴가 되었으며, 게임의 흐름상 불필요한 배치기 때문에 자시 제거
Debug.Log를 통해 오브젝트 파괴 유무 재점검을 통한 다른 원인을 고려해보았지만 싱글톤이 파괴되는것으로 확인됨
Solution
InGameSecene Hierarchy에서 Manager 오브젝트 하위에 RoundManager를 배치하였고 씬 전환으로 인한 부모오브젝트의 파괴로 자식오브젝트도 같이 파괴
RoundManager 배치를 최상위 오브젝트로 재배치. 이후, 다른 싱글톤에서 반복 실수를 방지하기 위해 아래 코드 추가한 후, 테스트한 결과 Issue 해결
Retrospective
Hierarchy에 오브젝트 배치에 있어 계층의 종속에 대한 이해와 중요성을 인지
메소드 내 로직상의 방어코드 뿐만 아니라 UI에 대한 방어코드 중요성을 인지
Issue
게임 재시작시 게임의 모든 정보를 초기화 하도록 함수를 구현하였지만 초기화 과정에서 슬롯에 배치된 조커카드가 삭제되지 않음
Process
각각의 정보를 초기화하는 함수에 Debug를 통해 확인했지만 구현한 의도대로 코드가 동작된것으로 확인되어 데이터는 정상초기화됨.
이 단계에서 데이터 외에 오브젝트도 파괴해야함을 인지
조커이미지(오브젝트) 제거를 위해 GameOver에 연결된 스크립트에서 OnDestroy 라이프사이클에서 오브젝트 Destroy를 시도하였으나 오브젝트가 여전히 유지.
초기화 함수를 진행할 때, 조커카드를 Destroy 시도하였지만 상황 유지
SetActive(false)를 통해 이미지를 안보이도록 시도하였지만 여전히 유지
조커카드 정보를 담고있는 hasJokerCards를 초기화하기 이전에 순회하여 Sprite를 null 처리를 시도하였지만 해결되지 않았고 추후 Sprite를 다시 연결해야할 수도 있기 때문에 접근이 잘못 되었음을 파악
Solution
조커카드가 jokerSlotArea 하위에 배치되어 생성되는데 조커슬롯이 해당 이슈 당시 싱글톤으로 구현되어 파괴되지 않았다보니 하위에 배치된 오브젝트 파괴되지 않은 것으로 추측
조커 슬롯 하위 오브젝트를 순회 후 파괴하도록 수정 후 테스트한 결과 Issue 해결
Retrospective
초기화의 개념은 단순한 데이터 초기화가 아닌 물리적인 오브젝트의 파괴도 고려하는것임을 학습
다른 오류가 발생하였을 때, UI와 연결되었다면 코드 오류만 확인하는 것이 아닌 Hierarchy의 배치상의 오류도 고려하게됨
Issue
점수 계산 도중 카드 클릭 활성화로 인하여 핸드의 남아있는 카드와 계산중인 카드가 클릭되어 오류 발생
Solution
점수 계산도중에는 SelectCard, Hands의 RayCast를 비활성화되도록 처리
Issue
테스트시 게임 설명 부재로 인한 테스트 진행의 어려움 발생 및 게임 플레이의 핵심 정보인 카드 족보의 이해도 부족으로 인해 튜토리얼의 필요성 인식
Solution
Title Scene(실행시 최초 화면)에서 Tutorial 버튼 생성 및 연결하여 게임 진행 방식을 안내
InGame, Clear, Shop Scene에서 ESC키 입력시 메뉴 활성화. 메뉴에 Rank정보, 음량 조절, 게임 재시작 등 기능을 추가 Rank정보의 경우 Tutorial과 동일한 방식으로 구현
최종 개발이 완료된 이후 회고하였을 때, 원작 Balatro와 비교하여 보완 필요한 기능을 기반으로 지속적인 유지보수 및 추가 구현을 진행하기 위한 예정사항을 작성함
현재 동일한 동작을 하지만 파라미터가 다르거나 세부적인 차이를 이유로 분리한 함수를 공통처리 필요
상속 구조를 통해 더 많은 로직을 BaseCard에 통합하여 재사용성 증진
속성 정리 및 함수 순서 변경등을 통한 코드 가독성 증가를 목표로함
조커카드 효과 다양화 및 카드 계산 흐름 보완
원작에 비해 부족한 수의 조커카드 효과를 제공하고 있어 게임의 재미와 더불어 다양한 전략으로 게임플 플레이할 수 있도록 더 다양한 조커카드 추가 예정
일부 조커카드의 경우 족보에 기여한 카드별 계산 도중 조커 효과가 발동되는데 현재는 미구현되어 있어 추가 예정
카드 강화 시스템 추가
PlayCard에 다양한 효과(카드 점수 강화, 삭제, 변경..)를 부여하는 TaroCard 미구현에 따른 추가 예정
게임 시작 전 다양한 모드 추가
현재는 고정된 수치로 게임 시작시 자원 제공
원작을 참고하여 게임 시작 전, 다양한 자원의 이점을 주거나 반대로 제약하는 모드를 구현하여 도전 욕구를 자극할 수 있는 시스템 구축 예정
업적 추가
게임 플레이를 기반으로 다양한 업적을 추가하여 달성욕구 자극
지금까지 사용한 카드들의 달성도를 시각화하여 플레이어에게 제공
처음 게임을 개발했다는 점에서는 시간가는줄 모르고 재밌게 했던것 같습니다.
원작과 비교하였을 때, 아직 보완해야할 게임의 요소들과 연출에 있어 미숙한 모습을 많이 보였지만 계속해서 고쳐나가기에는 끝이 없고 이제는 더 새로운 것들을 배워서 나중에 다시 이 게임을 고쳐나가는 것이 맞다고 판단되어 여기서 1차 개발을 마무리합니다.
지금은 비록 이미 잘 완성된 게임을 따라 만드는 것에 그쳤지만 더 잘 배워서 최종에는 제가 기획한 게임을 만들어볼 수 있도록 하겠습니다.