강화 재료와 비용 계산 구조
목차
1. 시스템 요구 사항
강화 대상 선택과 UI 동기화 구조를 정리한 이후, 강화 단계와 장비 타입에 따라 재료와 비용을 일관되게 계산하는 구조가 필요했다.
강화 단계가 올라갈수록 비용은 자연스럽게 증가해야 했고, 무기와 반지처럼 장비 성격이 다른 아이템들은 서로 다른 강화 한계와 비용 구조를 가져야 했다.
또한 강화 비용 계산 결과는 UI 표시, 버튼 활성화 여부, 경고 메시지 출력과 직접적으로 연결되기 때문에 계산 로직과 UI 출력이 섞이지 않는 구조가 필요했다.
단순히 수치를 계산하는 문제가 아니라, 강화 규칙이 늘어나더라도 구조가 무너지지 않는 비용 계산 흐름 구조 설계가 필요했다.
2. 흐름도

강화 비용과 강화 가능 여부 판단은 Update 루프 내에서 selectedItem이 존재할 경우에만 실행되며, 현재 강화 단계(selectedItem.grade)와 보유 재화 상태를 기준으로, 매 프레임 동일한 계산 흐름을 거치도록 구성하였다.
이 흐름을 통해 강화 규칙 변경, 재화 변화, 아이템 변경 상황에서도 UI와 로직이 항상 같은 기준으로 동기화되도록 했다.
3. 구현

위 표는 강화 단계와 장비 타입에 따라강화 재료와 비용이 어떻게 증가하도록 설계했는지를 정리한 것이다.
이 구조를 기준으로 강화 비용 계산 로직을 구현하였다.
3.1. 장비 타입에 따른 강화 규칙 분기
private void UpdateRequirementsByType()
{
if (selectedItem.equipType == Item.EquipType.Weapon)
{
SetAccordingToType(1, 10); // 무기: 비용 배율 1, 최대 강화 10
}
else
{
SetAccordingToType(2, 3); // 예: 반지: 비용 배율 2, 최대 강화 3
}
}
UpdateRequirementsByType 함수는 선택된 아이템의 타입(equipType)을 기준으로 비용 배율과 최대 강화 단계를 결정한다.
이 함수는 장비 타입(무기/반지)에 따라, 다른 강화 규칙이 적용될 수 있도록 실제 비용 계산을 수행하지 않고 필요한 규칙 정보만을 다음 단계(SetAccordingToType(int x, int maxGrade))로 전달한다.
이때 결정된 비용 배율(x)과 최대 강화 단계(maxGrade)는 매개변수 형태로 SetAccordingToType 함수에 전달된다.
장비 타입이 추가되더라도 이 단계에 규칙만 추가하면 되도록 구조를 유지하였다.
3.2. 강화 단계 기반 비용 계산
private void SetAccordingToType(int x, int maxGrade)
{
requiredCoin = (selectedItem.grade + 1) * 400 * x;
requiredCrystal = (selectedItem.grade + 1) * x;
if (selectedItem.grade < maxGrade)
{
upgradeInfo.text = $"{selectedItem.grade} > {selectedItem.grade + 1}";
crystalCount.text = $"{currentCrystalCount} / {requiredCrystal}";
reqCoin.text = $"필요 재화: {requiredCoin}";
}
else
{
upgradeInfo.text = "최대 강화";
crystalCount.text = "-";
reqCoin.text = "필요 재화: -";
}
}
SetAccordingToType 함수는 실제 강화 재료와 재화 계산을 수행한다.
이 함수는 현재 강화 단계와 전달받은 비용 배율을 기준으로 requiredCoin(강화에 필요한 재화)과 requiredCrystal(강화에 필요한 재료 수량)값을 계산한다.
강화 비용은 (현재 강화 단계 + 1)을 곱셈 인자로 사용하여, 강화 단계가 증가할수록 비용이 자연스럽게 증가하도록 구성하였다.
이를 통해 초반 강화는 부담이 적고, 후반 강화는 전략적 선택이 되도록 유도하였다.
현재 강화 단계가 최대 강화 단계보다 낮은 경우에는 다음 강화 단계, 필요 재화, 필요 크리스탈 수량을 UI에 즉시 반영한다.
반대로 최대 강화 단계에 도달한 경우에는 강화가 불가능한 상태임을 명확히 전달하기 위해 강화 정보 텍스트를 ‘최대 강화’ 로 표시하고, 필요 재화 관련 UI를 ‘-’ 로 처리한다.
이 단계에서 계산된 requiredCoin과 requiredCrystal은 이후 UpdateUpgradeState 함수에서 현재 보유 재화와 비교하는 기준 값으로 사용된다.
이로 인해, 비용 계산 단계와 강화 가능 여부 판단 단계가 변수 공유를 통해 연결된다.
3.3. 강화 가능 여부 판단
private void UpdateUpgradeState()
{
if (upgradeInfo.text == "최대 강화")
{
BtnOrErr(false, false);
return;
}
bool hasEnoughCrystal = currentCrystalCount >= requiredCrystal;
bool hasEnoughCoin = itemManager.coin >= requiredCoin;
if (hasEnoughCrystal && hasEnoughCoin)
BtnOrErr(true, false);
else
BtnOrErr(false, true);
}
비용 계산 이후에는 UpdateUpgradeState 함수에서 강화 시도가 가능한 상태인지 판단한다.
UpdateUpgradeState 함수는 강화 비용 계산 결과와 현재 보유 재화를 비교하여, 강화 가능 여부만 판단하는 역할을 수행한다.
먼저, 최대 강화 상태를 우선적으로 차단하여 이미 강화가 불가능한 경우 불필요한 재화 비교가 이루어지지 않도록 하였다.
이후 크리스탈과 재화를 각각 비교하여 두 조건이 모두 충족될 경우에만 강화 가능 상태로 판단한다.
판단 결과는 boolean 값으로 변환되어 강화 버튼과 경고 UI를 제어하는 BtnOrErr 함수로 즉시 전달된다.
이를 통해 강화 가능 여부 판단 로직과 UI 제어 로직을 분리하고, 재화 종류나 강화 조건이 변경되더라도 구조가 서로 영향을 주지 않도록 구성하였다.
현재는 UI 텍스트 기반으로 최대 강화 상태를 판별하고 있으나, 코드의 안정성과 유지보수성을 높이기 위해 향후 Enum 기반의 상태 관리 시스템으로 전환할 계획이다.
3.4. 버튼과 경고 UI 제어
public void BtnOrErr(bool btn, bool err)
{
upgradeBtn.SetActive(btn);
warningText.SetActive(err);
}
BtnOrErr 함수는 전달받은 판단 결과에 따라 강화 버튼과 경고 메시지를 활성화 또는 비활성화한다.
이 함수는 UI 제어만을 담당하며, 강화 비용 계산이나 조건 판단 로직과는 분리하였다.
4. 개발 의도
처음에는 강화 비용 계산과 UI 출력을 한 함수에서 처리하는 방식도 고려했다.
하지만 이 경우 강화 규칙이 늘어날수록 조건문이 증가하고 UI 수정이 곧 로직 수정으로 이어질 가능성이 컸다.
따라서, 장비 타입 판단, 비용 계산, 강화 가능 여부 판단, UI 출력을 단계별로 분리한 구조를 선택했다.
이 구조를 통해 강화 단계 조정, 장비 타입 추가, 밸런스 변경이 발생하더라도 기존 구조를 유지한 채 확장이 가능해졌고, UI 변경에도 영향을 받지 않는 강화 비용 계산 구조를 확보할 수 있었다.
