강화 대상 선택 및 강화 패널 동기화 구조

목차

1. 요구 사항

2. 설계 목표

3. 흐름도

4. 구현

       4.1. 강화 대상 선택 상태 관리

       4.2. 강화 시스템 처리 흐름 제어

       4.3. 강화 패널 UI 출력 동기화

       4.4. UI 상태 초기화

5. 개발 의도

1. 시스템 요구 사항

강화 시스템에서 가장 먼저 해결해야 했던 문제는 인벤토리에서 선택된 아이템 정보를 기준으로, 강화 패널의 UI와 강화 가능 상태를 어떻게 일관되게 동기화할 것인지가였다.

인벤토리에서 아이템을 선택했을 때,아이템 이미지, 이름, 강화 단계, 필요 재화가 즉시 강화 패널에 반영되어야 했고,

이후 강화 규칙이나 UI 구조가 변경되더라도 입력 처리 방식 자체는 영향을 받지 않아야 했다.

즉, 강화 시스템에서는 인벤토리 입력으로 전달된 아이템 정보를 기준으로,강화 패널의 UI와 강화 가능 상태를 한 프레임 내에서 일관되게 갱신할 필요가 있었다.

2. 설계  목표

- 인벤토리 입력과 강화 UI 로직을 직접 연결하지 않을 것

- 선택 이벤트 발생 후 한 프레임 내에서 UI, 비용, 버튼 상태가 동시에 갱신되도록 구성

- UI 구성 변경 시 로직 수정 최소화

- 이후 비용 계산, 조건 판단 로직이 자연스럽게 확장될 수 있는 구조

3. 흐름도

입력 이벤트는 선택 상태만 변경하고, 실제 UI 반영과 로직 처리는 Update 루프에서 수행하도록 설계했다.

이를 통해 입력 시점과 시스템 처리 시점을 분리하고, 한 프레임 내에서 모든 강화 관련 정보가 일관되게 갱신되도록 흐름을 구성하였다.

4. 구현

4.1. 강화 대상 선택 상태 관리
private Item selectedItem;

public void SelectItem(Item _item)
{
    selectedItem = _item;
}

강화 대상은 인벤토리 슬롯 클릭을 통해 전달된다.

강화 시스템은 아이템의 참조만 저장하고,강화에 필요한 정보는 이후 단계에서 분리하여 처리하도록 구성했다.

SelectItem(Item _item) 함수는 인벤토리 슬롯 클릭 시 호출되며, 외부에서 전달된 Item 객체의 참조를 내부 변수 selectedItem에 저장한다.

이 함수는 아이템 선택이라는 상태 변경만 수행하며, UI 갱신이나 강화 로직 실행은 포함하지 않는다.

강화 시스템은 이후 모든 처리를 selectedItem의 null 여부와 데이터에 의존하여 수행한다.

즉, 이 함수는 강화 시스템의 입력 진입점 역할을 하며, 현재 강화 대상으로 지정된 아이템 상태를 단일 변수로 관리한다.

이 구조에서는 강화 패널, 비용 계산, 버튼 활성화 여부 판단 등이 모두 selectedItem 상태를 기준으로 동작하며, 선택 입력과 강화 처리 로직이 코드 레벨에서 분리된다.

4.2. 강화 시스템 처리 흐름 제어
void Update()
{
    if (selectedItem != null)
    {
        UpdateSelectedItemUI();
        UpdateRequirementsByType();
        UpdateUpgradeState();
    }

    UpdateGradeImageVisibility();
}

private void UpdateGradeImageVisibility()
{
    gradeImage.enabled = (gradeImage.sprite != null);
}

Update함수는 선택된 아이템이 존재할 경우, 강화 패널에서는 해당 아이템의 기본 정보, 강화 비용, 강화 가능 여부를 한 프레임 내에서 함께 갱신한다.

초기에는 Update 함수 내부에서 아이템 선택 여부 판단, UI 표시, 강화 비용 계산, 강화 가능 여부 판단을 하나의 흐름으로 처리했다.

이로 인해 UI 수정이 필요할 경우 강화 로직까지 함께 수정해야 했고, Update가 과도한 책임을 가지게 되었다.

이에 따라 Update의 역할을선택된 아이템 존재 여부를 확인하고 처리 흐름을 제어하는 수준으로 축소하고, 실제 로직은 전용 함수로 분리하였다.

Update 함수는 강화 시스템의 프레임 단위 상태 동기화 레이어로 사용된다.

강화 패널은 선택된 아이템, 보유 재화 수량, 강화 단계 등의 상태에 따라 UI 출력과 강화 가능 여부가 실시간으로 동기화되어야 하는 구조이다.

특히 재화 수량은 강화 외에도 상점 구매, 보상 지급 등 외부 시스템에 의해 비동기적으로 변경될 수 있다.

이러한 상태 변화를 개별 이벤트로 모두 연결할 경우 강화 시스템이 재화 시스템, 인벤토리 시스템에 직접 의존하게 되며 시스템 간 결합도가 급격히 증가한다.

이를 피하기 위해 강화 패널은 selectedItem과 현재 재화 상태를 프레임 단위로 조회하는 방식을 선택하였다.

매 프레임 호출로 인한 비용을 고려하여, 실제 연산은 선택된 아이템이 존재할 경우에만 수행되도록 제한하였으며,
UI 갱신(UpdateSelectedItemUI), 강화 비용 계산(UpdateRequirementByType), 강화 가능 여부 판단(UpdateUpgradeState)을 각각의 함수로 분리하였다.

이를 통해 Update는 무거운 연산을 수행하는 로직 레이어가 아니라, 강화 시스템의 상태를 UI에 반영하는 경량 동기화 레이어로 동작하도록 구성하였다.

UpdateGradeImageVisibility는 이미 강화된 아이템이면 강화 단계 이미지를 활성화하고, 강회되지 않았으면 강화 단계 이미지 비활성화하는 로직이다.

4.3. 강화 패널 UI 출력 동기화
private void UpdateSelectedItemUI()
{
    icon.enabled = true;
    icon.sprite = selectedItem.itemImage;
    gradeImage.sprite = selectedItem.gradeSprite;
    itemName.text = selectedItem.itemName;
}

UpdateSelectedItemUI 함수는 선택된 아이템의 데이터를 강화 패널 UI에 반영하는 역할을 수행한다.
selectedItem에 저장된 아이템 이미지, 강화 단계 스프라이트, 아이템 이름을 읽어 각각 아이콘 이미지와 텍스트 UI에 할당한다.

이 함수는 UI 출력만을 담당한다.

강화와 관련된 조건 판단은 외부 로직에서 처리되고, 해당 함수는 계산 결과를 UI에 표시하는 단계로만 사용된다.

이와 같은 구조를 통해 강화 규칙이나 알고리즘이 변경되더라도 UI 출력 코드에는 영향을 주지 않으며, 강화 패널의 UI 구성이 변경될 경우에도 해당 함수만 수정하면 되도록 책임을 한정하였다.

4.4. UI 상태 초기화
public void CancelSelection()
{
    selectedItem = null;

    icon.enabled = false;
    icon.sprite = null;

    gradeImage.enabled = false;
    gradeImage.sprite = null;

    itemName.text = "";
    upgradeInfo.text = "";
    crystalCount.text = "";
    reqCoin.text = "";

    BtnOrErr(false, false);

    if (roulettePanel != null) roulettePanel.SetActive(false);
    if (resultPanel != null) resultPanel.SetActive(false);

    isRotating = false;
    upgradeAttempted = false;
}

CancelSelection 함수는 강화 패널에서 사용되는 모든 선택 상태와 UI 출력 상태를 초기화하는 상태 리셋 전용 함수이다.

함수 호출 시 먼저 selectedItem을 null로 설정하여 강화 대상이 존재하지 않는 상태로 전환하고, 이를 기준으로 이후 강화 관련 로직이 실행되지 않도록 한다.

이후 아이템 아이콘과 강화 단계 이미지에 대해 enabled를 false로 설정하고, 연결된 sprite 참조를 제거하여 이전 아이템의 시각적 정보가 화면에 남지 않도록 한다.

아이템 이름, 강화 정보, 재화 수량과 관련된 텍스트 UI는 빈 문자열로 초기화하여 강화 대상이 없는 상태임을 UI 상에서 명확히 표시한다.

BtnOrErr(false, false) 호출을 통해 강화 버튼과 오류 메시지의 활성 상태를 동시에 비활성화하고, 강화 가능 여부와 무관하게 입력이 차단된 상태로 되돌린다.

룰렛 패널과 결과 패널이 존재할 경우 SetActive(false)를 호출하여 비활성화함으로써, 강화 연출 도중이거나 결과 표시 상태에서 강화 대상이 변경되는 상황을 방지한다.

마지막으로 isRotating과 upgradeAttempted 플래그를 false로 설정하여, 강화 시도 과정에서 사용되던 내부 진행 상태를 모두 리셋한다.

이를 통해 이전 강화 시도의 상태가 다음 강화 처리에 영향을 주지 않도록 한다.

이 함수는 강화 패널의 UI 상태와 내부 강화 진행 상태를 하나의 진입점에서 일괄 초기화하여, 강화 시스템을 항상 동일한 시작 상태로 복구시키는 역할을 한다.

5. 개발 의도

처음에는 인벤토리 슬롯 클릭 시 강화 UI를 직접 갱신하는 방식도 고려했다.

하지만 이 방식은 UI 구조가 변경될 경우 인벤토리 코드까지 수정해야 하고, 강화 로직이 늘어날수록 시스템 간 의존성이 빠르게 증가할 수 있다고 판단했다.

이러한 문제를 고려하여, 입력 처리와 시스템 반영을 분리한 구조를 선택했다.

이 구조를 통해 강화 비용 계산, 강화 가능 조건 판단, 이후 확률 시스템까지 Update 루프 안에서 자연스럽게 확장할 수 있는 기반을 마련할 수 있었다.

결과적으로 인벤토리와 강화 패널 간의 데이터 흐름이 명확해졌고, UI 변경에도 영향을 받지 않는 구조를 확보할 수 있었다.

또한 강화 시스템이 확장되더라도 기존 코드 수정 없이 기능을 추가할 수 있어 유지보수성과 확장성을 동시에 만족시킬 수 있었다.