속성 상태 기준 비용 계산 및 UI 동기화 구조
1. 시스템 요구 사항
속성 부여 시스템의 두 번째 문제는 아이템의 현재 속성 상태에 따라 비용 UI와 입력 가능 상태가 항상 정확히 동기화되는가였다.
속성 부여는 단순히 재료를 소모하는 기능이 아니라, 현재 부여된 속성의 개수, 최대 속성 도달 여부, 그리고 추가 시도가 가능한 상태인지에 따라 UI와 입력 가능 여부가 즉시 달라져야 하는 시스템이다.
특히 속성 시스템은 강화 시스템과 달리 동일 아이템에 대해 여러 번 반복적으로 접근하며 상태가 누적되는 구조이기 때문에, 한 번의 계산 결과를 저장해두는 방식보다는 항상 현재 상태를 기준으로 판단하는 구조가 필요했다.
이 구조를 사용하지 않을 경우, 속성 결과가 반영된 이후에도 이전 비용 정보가 남아 있거나, 입력 가능 여부와 실제 상태가 어긋나는 문제가 발생할 수 있었다.
따라서 비용 UI와 입력 가능 상태는 항상 현재 아이템 상태를 기준으로 동기화되어야 했다.
2. 설계 목표
- 속성 최대 상태 여부를 하나의 기준 함수로 통합할 것
- 비용 계산과 UI 표시를 상태 기반으로 처리할 것
- 최대 속성 상태에서는 추가 입력을 명확히 차단할 것
- UI 텍스트와 로직 판단이 서로 다른 기준을 갖지 않도록 할 것
- 이후 확률 미니게임, 자동 실행 기능과도 자연스럽게 연동될 수 있는 구조를 만들 것
3. 흐름도

속성 시스템은 속성 부여 시점이나 결과 시점에 UI를 부분적으로 수정하지 않는다.
항상 Update 루프에서 ‘현재 아이템 상태 → 최대 상태 여부 → 비용 계산 → UI 출력’ 의 순서로 일괄 처리함으로써, 어떤 상태 변화 이후에도 이전 계산 결과가 UI에 남지 않도록 했다.
이 구조를 통해 속성 결과 반영, 재화 변화, 자동 실행 등 어떤 상태 변화가 발생하더라도 UI는 항상 동일한 기준으로 출력된다.
4. 구현
4.1. 최대 속성 상태 통합 관리
속성 최대 여부를 여러 조건문으로 흩뿌리지 않고, 하나의 함수로 통합해 관리하였다.
private bool IsMaxEnhanced()
{
return currentItem != null &&
currentItem.additionalStat != null &&
(currentItem.additionalStat.Length >= MaxPropertyCount ||
currentItem.isPropertyMax);
}
이 함수는 현재 아이템의 추가 속성 개수와 속성 최대 상태 플래그를 함께 고려하여 속성 부여가 가능한 상태인지 여부를 단일 기준으로 반환한다.
이후 비용 계산, UI 출력, 입력 차단 여부 판단은 모두 이 함수의 결과를 기준으로 동작한다.
이를 통해 어디에서는 최대 상태로 인식하고, 어디에서는 아닌 상태로 인식하는 문제를 구조적으로 차단할 수 있었다.
4.2. 보유 재료 UI 갱신 구조
보유 중인 속성 크리스탈 수량 역시 아이템 상태를 기준으로 매 프레임 갱신한다.
private void UpdateCrystalUI()
{
if (IsMaxEnhanced())
{
haveItemTxt.text = " ";
return;
}
Item crystalItem = im.GetItem(CrystalItemId);
haveItemTxt.text = crystalItem != null
? crystalItem.count.ToString()
: "0";
}
이미 최대 속성 상태라면 보유 재료 수량을 표시하지 않고,
추가 시도가 불가능하다는 상태를 UI적으로 명확히 드러내도록 구성했다.
이렇게 함으로써 재료는 충분하지만, 이미 최대 속성 상태로 인해 속성 부여가 불가능한 경우에도 플레이어가 혼란을 느끼지 않도록 구성하였다.
4.3. 속성 단계 기반 비용 계산 및 UI 출력
속성 비용은 현재 부여된 속성의 개수를 기준으로 계산된다.
private void UpdateUpgradeCostUI()
{
if (currentItem == null)
{
needItemTxt.text = "/ 0";
needCoinTxt.text = "0";
return;
}
if (IsMaxEnhanced())
{
needItemTxt.text = " ";
needCoinTxt.text = " ";
upgradeMaxWarningTxt.SetActive(true);
return;
}
upgradeMaxWarningTxt.SetActive(false);
int count = currentItem.additionalStat != null ? currentItem.additionalStat.Length : 0;
if (count == 0)
{
needItemTxt.text = "/ 1";
needCoinTxt.text = "2000";
}
else if (count == 1)
{
needItemTxt.text = "/ 2";
needCoinTxt.text = "3000";
}
}속성 단계가 증가할수록 필요한 재료와 재화가 자연스럽게 증가하도록 구성하였다.
최대 속성 상태에 도달한 경우에는 숫자 대신 공백과 경고 UI를 출력해 더 이상 속성 부여가 불가능한 상태임을 직관적으로 전달하였다.
현재는 속성 단계에 따라 비용을 분기 처리했지만, 이후 속성 타입이나 단계가 늘어날 경우 데이터 기반 구조로 자연스럽게 확장할 수 있도록 설계하였다.
5. 개발 의도
속성 시스템에서는 비용 계산 결과 자체보다 UI가 항상 신뢰 가능한 상태를 보여주는 것이 더 중요하다고 판단했다.
그래서 비용 계산 결과를 저장해두는 방식이 아니라, 매 프레임 현재 아이템 상태를 기준으로 UI를 다시 계산하고 출력하는 구조를 선택했다.
이 구조를 통해 속성 결과 반영, 재화 변화, 자동 실행 등 어떤 상태 변화가 발생하더라도 UI와 로직이 서로 다른 상태를 기준으로 동작하는 상황을 방지할 수 있었다.
속성 비용 UI와 최대 속성 상태 관리는 이후 확률 미니 게임 진입 조건과도 직접 연결되며, 이 비용 · 상태 구조를 기반으로 속성 부여 시도 검증과 미니 게임 진입 흐름을 다룬다.
