속성 부여 시도 검증 및 확률 미니 게임 진입 구조
1. 시스템 요구 사항
속성 부여 시스템의 세 번째 핵심은 조건이 충족되지 않은 상태에서 속성 부여 시도가 실행되는 상황을 구조적으로 차단하는 것이었다.
속성 부여는 아이템 선택 여부, 최대 속성 상태, 재화 보유량 등 여러 조건을 동시에 만족해야만 가능한 시도다.
이 중 하나라도 어긋난 상태에서 시도가 이루어질 경우, 재화 차감 오류나 잘못된 상태 전이가 발생할 수 있다.
따라서 버튼 클릭 시점에는 UI 상태를 신뢰하지 않고, 시스템 내부 상태를 기준으로 한 번 더 검증하는 단계가 필요했다.
2. 설계 목표
- 속성 부여 가능 여부를 시스템 기준으로 검증할 것
- 검증 실패 사유를 명확히 구분할 것
- 조건 만족 시 즉시 미니 게임으로 진입할 것
- 이후 자동 실행, 확률 시스템과 자연스럽게 연결될 수 있는 구조를 만들 것
3. 흐름도

속성 시스템은 버튼 클릭 시 UI에 표시된 정보가 아니라, 현재 아이템과 재화의 실제 상태를 기준으로 속성 부여 가능 여부를 다시 한 번 검증한다.
이를 통해 UI와 로직이 어긋난 상태에서 잘못된 속성 부여 시도가 발생하는 상황을 방지한다.
4. 구현
4.1. 속성 부여 시도 진입 조건 분기
속성 부여 버튼 클릭 시, 가장 먼저 현재 아이템의 상태를 확인한다.
public void UpgradeBtnClick()
{
if (currentItem == null) return;
if (IsMaxEnhanced())
{
StartCoroutine(ShowError(maxWarningTxt.gameObject, 0.5f));
return;
}
CheckAndUpgrade();
}이 단계에서는 속성 최대 상태 여부를 가장 먼저 차단하여,이미 더 이상 속성을 부여할 수 없는 경우에는 불필요한 재화 검증이나 미니게임 초기화를 수행하지 않도록 하였다.
초기 구현에서는 최대 속성 여부를 버튼 이벤트 내부에서 직접 비교하였기 때문에, 속성 부여 최대치 변경이나 조건 확장에 취약한 구조였다.
그래서 최대 부여 횟수를 MaxPropertyCount 상수로 정의하였다.
또한 최대 부여 여부 판단을 IsMaxEnhanced() 함수 하나로 통합하였다.
이를 통해 UI 갱신, 버튼 입력 제한, 속성 부여 로직 차단이 모두 동일한 기준으로 동작하도록 설계할 수 있었다.
부여 최대치가 변경되더라도 상수 값만 수정하면 전체 시스템에 반영되도록 구조화하였다.
4.2. 재화 및 재료 검증 구조
속성 부여 가능 상태로 판단된 경우에만 재화와 재료 보유량을 검증한다.
private void CheckAndUpgrade()
{
int upgradeCost = int.Parse(needCoinTxt.text);
string rawText = needItemTxt.text;
Match match = Regex.Match(rawText, @"\d+");
int requiredCrystals = match.Success ? int.Parse(match.Value) : 0;
Item crystalItem = im.GetItem(CrystalItemId);
bool hasEnoughCrystals = crystalItem != null &&
crystalItem.count >= requiredCrystals;
bool hasEnoughCoins = im.coin >= upgradeCost;
bool canUpgrade = currentItem != null &&
hasEnoughCoins &&
hasEnoughCrystals;
if (canUpgrade)
{
im.coin -= upgradeCost;
crystalItem.count -= requiredCrystals;
InitializeMiniGame();
}
else
{
StartCoroutine(ShowError(warningTxt.gameObject, 0.2f));
}
}
비용 정보는 UI 텍스트를 그대로 신뢰하지 않고, 필요 수량만 추출해 시스템 로직에서 재검증한다.
이를 통해 UI 포맷이 변경되더라도 속성 부여 검증 로직이 영향을 받지 않도록 구성하였다.
초기 구현에서는 UI 텍스트를 그대로 파싱해 속성 부여 가능 여부를 판단했지만, UI 표현 방식 변경 시 로직이 함께 깨질 수 있는 구조였다.
이를 보완하기 위해 UI 텍스트를 그대로 신뢰하지 않고, 정규식을 사용해 숫자 값만 추출하였다.
Regex.Match(@"\\d+")는 문자열 포맷이 “/ 1”, “필요 수량 : 2개”처럼 변경되더라도, 숫자 정보만 안정적으로 분리할 수 있게 해준다.
이 방식은 UI를 데이터 소스로 삼는 것이 아니라, 상태 기반으로 갱신된 UI를 검증 단계에서 참고하는 구조이기 때문에, MVC 관점에서도 표현 계층과 로직 계층의 책임이 충돌하지 않는다.
이를 통해 UI 표현 형식이 변경되더라도 내부 속성 부여 로직은 영향을 받지 않도록 설계되었다.
UI 텍스트를 파싱하는 방식은 이상적으로 보이지 않을 수 있지만, 이 시스템에서는 UI가 항상 상태 기반으로 갱신되기 때문에, UI를 표현용 캐시로 활용해도 상태 불일치가 발생하지 않는다.
또한 재화 검증 로직을 코인 검증과 크리스탈 검증으로 나누어 처리하였다.
이를 통해 속성 부여 가능 여부 판단 과정이 보다 명확하고 읽기 쉬운 흐름으로 개선되었다.
속성 부여 시도 시점에 재화를 즉시 차감하도록 설계하여, 부여 실패 또한 하나의 비용이 드는 선택으로 인식되도록 구성하였다.
이를 통해 속성 부여 시스템의 긴장감과 선택의 무게를 유지하였다.
4.3. 확률 미니 게임 초기화 및 진입
모든 조건을 만족한 경우에만 확률 미니게임을 초기화하고 활성화한다.
private void InitializeMiniGame()
{
probabilityButtonManager.InitializeMiniGame();
miniGame.SetActive(true);
randomIndex = Random.Range(0, upgradelist.Count);
upgradeInfoTxt.text = upgradelist[randomIndex];
warningTxt.gameObject.SetActive(false);
}
이 시점에서 재화 차감과 미니게임 진입이 동시에 이루어지도록 설계하여, 속성 부여 시도가 하나의 명확한 선택으로 인식되도록 하였다.
이후의 성공·실패 판정은 미니게임과 확률 시스템에서만 처리된다.
5. 개발 의도
속성 부여 시스템에서는 버튼 클릭을 속성 부여 실행으로 보지 않고, 속성 부여 시도에 진입하기 위한 요청으로 해석했다.
그래서 버튼 클릭 이후에도 아이템 상태, 최대 속성 여부, 재화 보유량을 시스템 기준으로 다시 한 번 검증하도록 구성했다.
이 구조를 통해 UI 표시 오류나 상태 불일치로 인한 잘못된 속성 부여 시도를 구조적으로 차단할 수 있었다.
속성 부여 시도 검증과 미니게임 진입은 다음 단계인 확률 변화, 자동 실행, 최종 속성 결과 처리의 기준점 역할을 한다.
이로 인해 속성 부여 시스템은 '시도 → 검증 → 실행' 이라는 단계가 명확히 분리된 구조를 갖게 되었다.
