XR플밍 - 12. UnityEngine3D Reactive 프로그래밍 - 기업협약 프로젝트 11일차 (9/1)

이형원·2025년 9월 1일
0

XR플밍

목록 보기
183/215
post-thumbnail

1. 금일 한 업무

  • 편성 프리셋 확장 시 3번째 슬롯을 개방하지 않은 채로 4번째 슬롯을 개방하려 할 때 발생하는 인덱스 에러 버그 수정
  • 가챠 시스템에서의 쿨타임 UI가 정상출력되지 않는 문제 해결
  • 마법석 가챠 UI 추가
  • 그 외 버그 픽스

2. 문제의 발생과 해결 과정

2.1 편성 프리셋 버그 수정

편성 프리셋 버그를 발견했을 때, 이를 위한 해결 방법이 기획 의도에 따라 해결방법이 달라졌다. 따라서 기획팀에게 요청하여 해당 내용을 확인 받았다.

이에 따라 2번 슬롯까지만 활성화되어 있는 상태일 시 3번 버튼까지만 눌릴 수 있게 UI 로직을 수정했다.

2.2 가챠 시스템 UI 버그 수정

가챠 시스템의 UI 버그로는 크게 두 가지 버그가 발생했다.

  • 12시간 쿨타임의 광고 버튼의 경우 쿨타임이 이상하게 출력됨.(ex) 3분 뒤에 충전되야 하는 상태에서 쿨타임이 11시간 57분으로 표기됨)

  • 쿨타임이 0분이 된 상태에서 쿨타임 UI가 업데이트 되지 않음

이 문제를 해결하기 위해 아래와 같이 코드를 수정했다.

using System;
using UnityEngine;
using UnityEngine.UI;

public class RandomGachaSystem : MonoBehaviour
{
    [Header("Reference")]
    [SerializeField] private CharacterDatabase _data;
    [SerializeField] private ItemProbabilitySO _prob;
    [SerializeField] private GachaResultUI _resultUI;

    [Header("GachaListUIButton")]
    [SerializeField] private Button _characterGachaButton;
    [SerializeField] private Button _stoneGachaButton;

    [Header("GachaListUI")]
    [SerializeField] private GameObject _characterGacha;
    [SerializeField] private GameObject _stoneGacha;

    [Header("CharacterGachaUI")]
    [SerializeField] private Button _dailyCharacterGachaButton;
    [SerializeField] private Button _oneCharacterGachaButton;
    [SerializeField] private Button _tenCharacterGachaButton;

    [Header("MagicStoneGachaUI")]
    [SerializeField] private Button _dailyStoneButton;
    [SerializeField] private Button _oneStoneGachaButton;
    [SerializeField] private Button _tenStoneGachaButton;

    // 확률 소수점 자릿수
    [Header("ProbOffset")]
    [SerializeField] private int digits = 0;

    private WeightedRandom<Grade> _gradeRandom = new WeightedRandom<Grade>();

    private void Awake()
    {
        Init();
    }

    private void Init()
    {
        RandomInit(_prob);

        _characterGachaButton.onClick.AddListener(() => SetActivePanel("CharacterGacha"));
        _stoneGachaButton.onClick.AddListener(() => SetActivePanel("MagicStoneGacha"));

        _dailyCharacterGachaButton.onClick.AddListener(AdButtonClick);
        _oneCharacterGachaButton.onClick.AddListener(OneButtonClick);
        _tenCharacterGachaButton.onClick.AddListener(() => ConsumeGoodsButtonClick(10));
    }

    private void RandomInit(ItemProbabilitySO probability)
    {
        for (int i = 0; i < probability.ItemsProbability.Count; i++)
        {
            Grade grade = probability.ItemsProbability[i].ItemGrade;
            int value = (int)(probability.ItemsProbability[i].Probability * (int)Math.Pow(10, digits));
            _gradeRandom.Add(grade, value);
        }
    }

    #region Button Click Event

    #region GachaListButton

    private void SetActivePanel(string activePanel)
    {
        _characterGacha.SetActive(activePanel.Equals(_characterGacha.name));
        _stoneGacha.SetActive(activePanel.Equals(_stoneGacha.name));
    }

    #endregion

    #region CharacterGachaButton

    private void AdButtonClick()
    {
        if(DailyAdGacha()) return;

        if(PopupManager.Instance != null)
        {
            PopupManager.instance.ShowPopup("일일 광고 가챠를 전부 사용하였습니다.");
        }
    }
    private bool DailyAdGacha()
    {
        if (TimeManager.Instance.CanObtainAdGachaReward())
        {
            TimeManager.Instance.SaveAdGachaResetTimeInfo();
            ItemSelect(1);
            TimeManager.Instance.OnDailyGachaInfoChanged?.Invoke();
            return true;
        }

        return false;
    }

    private void OneButtonClick()
    {
        if (DailyFreeGacha()) return;

        // 재화 소모 일시로 막아둠(신원님 요청)
        //ItemSelect(1);

        if (PopupManager.Instance != null)
        {
            PopupManager.instance.ShowPopup("일일 무료 가챠를 이미 진행하였습니다.");
        }
    }

    private bool DailyFreeGacha()
    {
        if (TimeManager.Instance.CanObtainedFreeGachaReward())
        {
            TimeManager.Instance.SaveDailyFreeGachaResetTimeInfo();
            ItemSelect(1);
            TimeManager.Instance.OnDailyGachaInfoChanged?.Invoke();
            return true;
        }
        return false;
    }    

    private void ConsumeGoodsButtonClick(int number)
    {
        // 재화 상태 확인 절차 진행

        ItemSelect(number);
    }

    #endregion

    #endregion

    #region 가중치 확률 선택

    // 확률 변동이 없는 가중치 확률
    private void ItemSelect(int number)
    {
        if (_gradeRandom.GetList() == null) RandomInit(_prob);

        for (int i = 0; i < number; i++)
        {
            UnitData data = ReturnData();
            _resultUI.HeroGachaUpdate(data, i);
        }

        _resultUI.gameObject.SetActive(true);
    }

    // 확률 변동 없는 캐릭터 뽑기
    private UnitData ReturnData()
    {
        Grade grade = _gradeRandom.GetRandomItem();
        return _data.GetRandomUnitByGrade(grade);
    }


    // 천장이 있는 가중치 확률
    private void ItemSelectBySub(int number)
    {
        if (_gradeRandom.GetList() == null) RandomInit(_prob);

        for (int i = 0; i < number; i++)
        {
            ReturnDataBySub();
        }
    }

    // 확률 변동 있는 캐릭터 뽑기
    private UnitData ReturnDataBySub()
    {
        Grade grade = _gradeRandom.GetRandomItemBySub();
        return _data.GetRandomUnitByGrade(grade);
    }

    #endregion
}

3. 개선점 및 과제

3.1 전체적인 데이터 교체 및 버그 수정

3.2 시너지 시스템 UI 반영

3.3 마법석 UI 추가

3.4 리팩토링 및 버그 수정

profile
게임 만들러 코딩 공부중

0개의 댓글