이번 프로젝트에서는 유니티 기반의 게임에서 몬스터 처치 후 발생하는 보상 아이템을 드롭 테이블 기반으로 계산하고, UI에 시각적으로 표현하는 기능을 구현하였습니다.
보상 드롭 로직은 기존에 제작해두었던 가챠 시스템의 가중치 기반 추첨 알고리즘을 응용하여 구성하였으며, 사용자에게 시각적으로 직관적인 보상 결과를 제공하는 것을 목표로 하였습니다.
구현 목표 및 개요
- 몬스터 처치 시 확률 기반 보상 아이템을 계산
- 드롭된 아이템을 RewardItem 형태로 저장
- UI에 정렬된 형태로 표시
- 수량이 1개인 보상 아이템은 수량 텍스트를 생략
1. 보상 아이템 저장 구조
드롭된 보상 아이템은 다음과 같은 RewardItem 클래스를 통해 정의됩니다.
public class RewardItem
{
public ItemData ItemData;
public int amount;
}
보상 아이템은 Dictionary 형태로 저장되며, 동일한 아이템이 중복 드롭될 경우 수량을 누적합니다.
2. 보상 드롭 처리 (RewardSystem 클래스)
TakeReward 클래스에서는 드롭 테이블 정보를 기반으로 아이템을 무작위 추출하고, 해당 정보를 보상 리스트에 누적합니다.
public void DropItem()
{
int dropItemKey = GetDropItemKey(dropTableKey);
AddItem(dropItemKey);
}
아이템 추가 처리:
private void AddItem(int item)
{
ItemData itemData = GameManager.Instance.Player.inventory.items[item].data;
if (rewardList.ContainsKey(item))
{
rewardList[item].amount++;
}
else
{
rewardList.Add(item, new RewardItem { ItemData = itemData, amount = 1 });
}
}
3. 가중치 기반 추첨 알고리즘 적용
보상 아이템 추출은 기존에 구현한 가챠 시스템의 가중치 기반 랜덤 추첨 구조를 그대로 재활용하였습니다.
이 로직은 DropEntryTable에서 설정된 확률 값을 기반으로 추첨이 이루어집니다.
public int GetDropItemKey(int dropTableKey)
{
var filtered = dropEntryTable
.Where(e => e.dropTable == dropTableKey)
.OrderBy(e => Random.value) // 무작위 정렬을 통해 동일 확률 시 편향 제거
.ToList();
float totalWeight = filtered.Sum(e => e.weight);
float rand = Random.Range(0, totalWeight);
float cumulative = 0f;
foreach (var entry in filtered)
{
cumulative += entry.weight;
if (rand <= cumulative)
return entry.item;
}
return -1;
}
4. 보상 UI 구성
사용자에게 보상 결과를 명확하게 전달하기 위해, 드롭된 아이템은 UI 상에 정렬된 슬롯 형태로 출력됩니다.
4-1. RewardUI
보상 리스트를 순회하며 프리팹으로 UI 슬롯을 생성합니다.
public void SetRewardUI(Dictionary<int, RewardItem> rewardList)
{
foreach (var rewardItem in rewardList.OrderBy(r => r.Key))
{
RewardSlots rewardSlots = Instantiate(rewardSlotsPrefabs, spwonPoint);
rewardSlots.SetData(rewardItem.Value);
}
}
4-2. RewardSlots
슬롯 UI 내에 아이콘 및 수량을 설정합니다.
public void SetData(RewardItem rewardItem)
{
if (rewardItem == null || rewardItem.ItemData == null)
{
Debug.LogError("RewardItem 또는 ItemData가 null입니다.");
return;
}
if (rewardItem.ItemData.icon != null)
itemIcon.sprite = rewardItem.ItemData.icon;
int amount = rewardItem.amount;
itemAmountText.text = amount.ToString();
if (amount == 1)
itemAmountText.enabled = false;
}
5. 실제 적용 결과 화면
아래는 전투 종료 후 보상 UI가 출력되는 실제 게임 화면입니다.
- 보상 아이템은 Key 기준 오름차순으로 정렬되어 출력됨
- 아이콘 및 수량이 명확히 표시되며, 수량이 1개일 경우 숫자 텍스트는 생략됨
- UI는 전투 결과 화면과 함께 자연스럽게 통합되어 있음
마무리
이번 보상 시스템 구현 과정에서는 기존에 제작한 가중치 추첨 로직을 구조화하여 재활용하는 것의 중요성을 체감하였습니다.
드롭 테이블 구조를 데이터 중심으로 분리하고, UI는 독립적으로 처리한 결과, 유지보수와 확장성이 모두 향상되었습니다.
'내일배움캠프 > Unity Final Projcet' 카테고리의 다른 글
[Unity] 경량화와 재사용을 위한 오브젝트 풀 구조 설계하기 (0) | 2025.04.23 |
---|---|
[Untiy] AudioMixer 기반의 BGM & SFX 사운드 매니저 제작하기 (0) | 2025.04.22 |
[Unity] GridLayoutGroup에서 마지막 줄이 가운데 정렬되지 않을 때 해결 방법 (트러블슈팅) (0) | 2025.04.18 |
[Unity] 2단계 확률 기반 가챠 시스템 (0) | 2025.04.17 |
[Unity] UI 패널 전환 효과를 DOTween으로 구현하기 (0) | 2025.04.16 |