오늘은 Balatro의 JokerCard를 구매할 수 있는 상점을 구현한 내용을 정리해보겠습니다.
상점은 다음과 같은 내용으로 기획하였습니다.
상점에 구현할 기능
1. 상품 리스트 노출(조커 카드 노출)
2. 상품 새로고침(Reroll)
3. 상품 구매(Buy)
4. InGame Scene 전환(Next Round)
기능 흐름
1. Clear Scene에서 획득한 Coin과 Player의 보유코인이 합산됨과 동시에 Shop Scene으로 전환한다.
2. 상점에 입장하면 JokerCard 2장이 상품칸에 진열된다.
3. JokerCard 진열 기준은 JokerSlot에 보유한 JokerCard를 제외한 상품을 표시한다.
4. JokerCard는 구매할 경우 JokerSlot으로 배치된다.
5. 마음에 드는 JokerCard가 없을 경우 Reroll버튼을 통해 상품을 새로고침할 수 있다.
6. 구매 및 리롤은 Player의 보유 코인여부를 확인하고 구매 및 새로고침 처리가 이루어진다.
상점은 다음과 같이 기능을 담당하는 ShopManager와 UI를 담당하는 ShopUI로 나누어 코드를 구현하였습니다.
ShopManager.cs
<style>
public void ShowJokerCards()
{
if (JokerSlot.Instance == null) return;
if (JokerSlot.Instance.hasJokerCards == null) return;
HashSet<JokerEffectType> hasJoker = new HashSet<JokerEffectType>();
foreach (var joker in JokerSlot.Instance.hasJokerCards)
{
if (joker != null) hasJoker.Add(joker.effectType);
}
for (int i = 0; i< remainJokerList.Count; i++)
{
if (hasJoker.Contains(remainJokerList[i].effectType))
{
Destroy(remainJokerList[i].gameObject);
remainJokerList.RemoveAt(i);
i--;
}
}
ShuffleAndDrawJokerCards();
}
public void RerollProduct()
{
if (rerollCost == 0) return;
rerollCost += rerollCount;
if (!RoundManager.Instance.CheckPlayerCoin(rerollCost)) return;
RoundManager.Instance.ConsumePlayerCoin(rerollCost);
rerollCount++;
RoundManager.Instance.UpdateRecord("Rerolled", rerollCount);
shopUI.UpdateShopInfo();
if (selectJoker != null) selectJoker.VisualSelect(false);
selectJoker = null;
ShowJokerCards();
}
</style>
ShopUI.cs
<style>
public void RefreshJokerDisplay(List<JokerCard> jokerCards)
{
ClearJokerSlots();
foreach (JokerCard card in jokerCards)
{
card.gameObject.SetActive(true);
card.transform.SetParent(jokerProductArea);
card.transform.localScale = Vector3.one;
card.transform.localPosition = Vector3.zero;
}
UpdateShopInfo();
}
</style>
상황
동일한 JokerCard가 상점에 계속 노출된다.
원인 분석
HashSet에 중복을 체크하는곳에 문제가 생긴것 같다.
확인해보니 HashSet에는 정상적으로 들어갔다.
HashSet 추가 후, Contains로 비교를 진행하는데 여기에서 오류가 발생하였다.
찾아보니 HashSet에서 JokerCard를 타입으로 받다보니 객체 참조 비교에서 문제가 발생하였다.
객체의 경우 메모리 주소를 비교하고 새로운 카드가 생성되는 시점에 객체참조 비교가 이루어지지않았다.
해결
JokerCard 객체 자체를 비교하는 것이 아닌 카드별 고유한 JokerEffectType을 비교하는 방식으로 진행하기 위해 HashSet<JokerEffectType>으로 수정하여 비교하는방식으로 진행하였다.