using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; using Random = UnityEngine.Random; public class GachaUI : uScrollViewMgr { public GameObject[] gos_grade; public Slider[] slider_lucky, slider_lucky2; public Image[] images_slider; // 알파 슬라이더 이미지들 public GameObject[] gos_sliderhandle; public TextMeshProUGUI[] texts_money; // 0 앨범 오픈 재화, 1 챗 코인, 2 가챠 코인 public TextMeshProUGUI[] texts; // 0 럭키 %, 1 광고 충전량, 2 가챠 필요량, 3 충전 시간, 4 차징 시 획득량, 5 가챠 획득량 public TextMeshProUGUI[] texts_luckypoint; // 획득한 럭키 포인트들 public GameObject go_CanEnterLuckyGame, go_autocharge; public Image i_Chest, i_GachaReward; public Slider slider_charge; public GachaLuckyResult m_GachaLuckyResult; DateTime GachaAutoRefillTime; float fRefillTime, ToastY = -400f; List<(eMoney, int)> list_log = new List<(eMoney, int)>(); Coroutine co_sliderupdate; private void Start() { texts[1].text = $"{table_GlobalValue.Ins.Get_Float("GachaAD_Reward")}"; texts[2].text = $"{table_GlobalValue.Ins.Get_Int("GachaAmount")}"; texts[4].text = $"{table_GlobalValue.Ins.Get_Int("GachaAmount")}"; videoPlayer.loopPointReached += OnVideoEnd; } private void Update() { if (!SaveMgr.Ins.Check_Money(eMoney.Gacha, table_GlobalValue.Ins.Get_Int("GachaAmount"), false)) { var cal = GachaAutoRefillTime - InternetTime.Ins.Time; fRefillTime -= Time.deltaTime; if (cal.TotalSeconds <= 0) fRefillTime = 0f; texts[3].text = fRefillTime > 0f ? $"{fRefillTime:F1}s" : "0s"; var fRefillTimeMax = table_GlobalValue.Ins.Get_Float("GachaAutoRefill_DelayTime"); if (SaveMgr.Ins.GachaChargeTime_Reduce()) fRefillTimeMax -= fRefillTimeMax * 0.9f; slider_charge.value = DSUtil.Get_SliderValue(fRefillTime / fRefillTimeMax); if (cal.TotalSeconds <= 0 && fRefillTime <= 0f) { SaveMgr.Ins.Add_Money(eMoney.Gacha, table_GlobalValue.Ins.Get_Int("GachaAutoRefill_Amount")); SaveMgr.Ins.Save(); LobbyUI.Ins.m_ToastUI.Set("별 코인이 자동 충전되었습니다.", ToastY); Set_Money(); } } } public void Set() { gameObject.SetActive(true); SoundInfo.Ins.Play_BGM(eBGM.b005_Gacha); DSUtil.InActivateGameObjects(gos_grade); for (int i = 0; i < texts_luckypoint.Length; i++) texts_luckypoint[i].alpha = 0f; Set_UI(false); Init_GachaAnim(); Set_Video(); var cal = GachaAutoRefillTime - InternetTime.Ins.Time; if (cal.TotalMilliseconds > 0f) fRefillTime = (float)cal.TotalMilliseconds * 0.001f; } void Set_UI(bool updateSlider) { if (updateSlider) { if (co_sliderupdate != null) StopCoroutine(co_sliderupdate); co_sliderupdate = StartCoroutine(Co_UpdateSlider()); } else { var cal = SaveMgr.Ins.Get_Money(eMoney.Lucky) / table_GlobalValue.Ins.Get_Float("LuckyPoint"); slider_lucky[0].value = slider_lucky[1].value = DSUtil.Get_SliderValue(cal); slider_lucky2[0].value = slider_lucky2[1].value = DSUtil.Get_SliderValue(cal - 1f); images_slider[0].color = images_slider[1].color = Color.white; texts[0].text = MyText.Get_PercentValueText_100_NoPoint(cal > 2f ? 2f : cal); Set_SliderHandle(); } go_CanEnterLuckyGame.SetActive(SaveMgr.Ins.Get_Money(eMoney.Lucky) >= table_GlobalValue.Ins.Get_Float("LuckyPoint")); Set_Money(); } void Set_SliderHandle() { gos_sliderhandle[0].SetActive(slider_lucky[0].value < 1f); gos_sliderhandle[1].SetActive(slider_lucky[0].value >= 1f); } IEnumerator Co_UpdateSlider() { float lucky = SaveMgr.Ins.Get_Money(eMoney.Lucky) / table_GlobalValue.Ins.Get_Float("LuckyPoint"); float targetValue1 = Mathf.Min(lucky, 1f); // slider_lucky 목표 slider_lucky[1].value = targetValue1; float targetValue2 = Mathf.Max(lucky - 1f, 0f); // slider_lucky2 목표 slider_lucky2[1].value = targetValue2; gos_sliderhandle[0].SetActive(slider_lucky[0].value < 1f); gos_sliderhandle[1].SetActive(slider_lucky[0].value >= 1f); float duration = 0.5f; // 각 슬라이더당 시간 float elapsed = 0f; // slider_lucky 먼저 var slider = slider_lucky[0]; var slider2 = slider_lucky2[0]; float startValue1 = slider.value; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); slider.value = Mathf.Lerp(startValue1, targetValue1, t); texts[0].text = MyText.Get_PercentValueText_100_NoPoint(slider.value + slider2.value); Set_SliderHandle(); yield return null; } slider.value = targetValue1; texts[0].text = MyText.Get_PercentValueText_100_NoPoint(slider.value + slider2.value); // slider_lucky2 다음 elapsed = 0f; float startValue2 = slider2.value; while (elapsed < duration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / duration); slider2.value = Mathf.Lerp(startValue2, targetValue2, t); texts[0].text = MyText.Get_PercentValueText_100_NoPoint(slider.value + slider2.value); Set_SliderHandle(); yield return null; } slider2.value = targetValue2; texts[0].text = MyText.Get_PercentValueText_100_NoPoint(slider.value + slider2.value); } void Set_Money() { texts_money[0].text = SaveMgr.Ins.Get_Money(eMoney.AlbumOpen).ToString(); texts_money[1].text = SaveMgr.Ins.Get_Money(eMoney.Chat).ToString(); texts_money[2].text = SaveMgr.Ins.Get_Money(eMoney.Gacha).ToString(); go_autocharge.SetActive(!SaveMgr.Ins.Check_Money(eMoney.Gacha, table_GlobalValue.Ins.Get_Int("GachaAmount"), false)); } public void OnClick_Lucky() { if (SaveMgr.Ins.Check_Money(eMoney.Lucky, table_GlobalValue.Ins.Get_Int("LuckyPoint"), true, ToastY)) { Init_GachaAnim(); SaveMgr.Ins.Add_Money(eMoney.Lucky, -table_GlobalValue.Ins.Get_Int("LuckyPoint")); var randomalbum = SaveMgr.Ins.Get_RandomAlbum(); if (randomalbum != null) SaveMgr.Ins.Open_Album(randomalbum); else SaveMgr.Ins.Add_Money(eMoney.AlbumOpen, table_GlobalValue.Ins.Get_Int("LuckyGachaMaxHeart_Amount")); SaveMgr.Ins.Save(); // 럭키가챠 UI 노출 (new) m_GachaLuckyResult.Set(randomalbum); // 기존 럭키 게임 (old) //LobbyUI.Ins.m_Game_Lucky.Set(); Set_UI(false); LobbyUI.Ins.m_LobbyCenterProfileUI.Set(false); } } public void OnClick_AD() { if (SaveMgr.Ins.CanShowGachaAD()) { ADInfo.Ins.Show_AD(false, () => { SaveMgr.Ins.Add_Money(eMoney.Gacha, table_GlobalValue.Ins.Get_Int("GachaAD_Reward")); SaveMgr.Ins.Save(); LobbyUI.Ins.m_ToastUI.Set($"뽑기 재화 {table_GlobalValue.Ins.Get_Int("GachaAD_Reward")}개를 획득했습니다.", ToastY); Set_Money(); }); } } public void OnClick_Gacha() { if (!isGacha && SaveMgr.Ins.Check_Money(eMoney.Gacha, table_GlobalValue.Ins.Get_Int("GachaAmount"), true, ToastY)) { isGacha = true; Init_GachaAnim(); PlayVideo(); } } public GameObject[] gos_effect; bool isGacha = false; void Init_GachaAnim() { DSUtil.InActivateGameObjects(gos_effect); DSUtil.InActivateGameObjects(gos_grade); i_Chest.gameObject.SetActive(false); i_GachaReward.transform.parent.parent.gameObject.SetActive(false); } IEnumerator Co_Gacha() { isGacha = true; Init_GachaAnim(); i_Chest.sprite = UIAtlasMgr.Ins.Get_Sprite($"GameBox-{Random.Range(0, 20)}"); gos_effect[5].SetActive(true); // 바닥 컬라이더 SoundInfo.Ins.Play_OneShot((eSound)Random.Range(12, 14)); i_Chest.gameObject.SetActive(true); var rb2d = i_Chest.GetComponent(); rb2d.linearVelocity = Vector2.zero; // 이동 속도 초기화 rb2d.angularVelocity = 0f; // 회전 속도 초기화 rb2d.transform.rotation = Quaternion.identity; // 회전 초기화 i_Chest.GetComponent().anchoredPosition = Vector2.up * 2000f; yield return new WaitForSeconds(1.1f); // 바닥에 상자 부딪혔을 때 이펙트 gos_effect[0].SetActive(true); yield return new WaitForSeconds(1.1f); i_Chest.gameObject.SetActive(false); yield return StartCoroutine(GachaReward()); } IEnumerator GachaReward() { yield return new WaitForSeconds(4f); yield return GachaReward2(); } IEnumerator GachaReward2() { SaveMgr.Ins.Add_Money(eMoney.Gacha, -table_GlobalValue.Ins.Get_Int("GachaAmount")); var gradedata = table_gacharateconfig.Ins.Get_RadomData(); var reward = table_gachareward.Ins.Get_Reward(gradedata.n_GachaGrade); i_GachaReward.transform.parent.parent.gameObject.SetActive(true); i_GachaReward.sprite = UIAtlasMgr.Ins.Get_Sprite(reward.Item1); switch (reward.Item1) { case eMoney.AlbumOpen: SoundInfo.Ins.Play_OneShot(eSound.s006_MiniGameGetHeart); break; case eMoney.Chat: SoundInfo.Ins.Play_OneShot(eSound.s007_MiniGameGetChatCoint); break; case eMoney.Gacha: SoundInfo.Ins.Play_OneShot(eSound.s008_MiniGameGetGachaCoin); break; } SaveMgr.Ins.Add_Money(reward.Item1, reward.Item2); texts[5].text = reward.Item2.ToString(); SaveMgr.Ins.Add_Money(eMoney.Lucky, reward.Item3); SaveMgr.Ins.Save(); list_log.Add((reward.Item1, reward.Item2)); if (reward.Item3 > 0) for (int i = 0; i < texts_luckypoint.Length; i++) { if (texts_luckypoint[i].alpha <= 0f) { texts_luckypoint[i].text = $"+{reward.Item3}"; texts_luckypoint[i].GetComponent().Play("Gacha_LuckyPoint"); break; } } //list_log.Add((eMoney.Lucky, reward.Item3)); Set_ScrollView(list_log); Set_Vertical_ScrollEnd(0); Set_UI(true); fRefillTime = table_GlobalValue.Ins.Get_Float("GachaAutoRefill_DelayTime"); if (SaveMgr.Ins.GachaChargeTime_Reduce()) fRefillTime -= fRefillTime * 0.9f; GachaAutoRefillTime = InternetTime.Ins.Time.AddSeconds(fRefillTime); switch (gradedata.n_GachaGrade) { case 1: case 2: case 3: gos_effect[1].SetActive(true); break; case 4: case 5: gos_effect[2].SetActive(true); break; case 6: case 7: gos_effect[3].SetActive(true); break; case 8: case 9: gos_effect[4].SetActive(true); break; } yield return new WaitForSeconds(0.5f); switch (gradedata.n_GachaGrade) { case 1: case 2: gos_grade[0].SetActive(true); break; case 3: break; default: DSUtil.InActivateGameObjects(gos_grade, gradedata.n_GachaGrade - 2); break; } isGacha = false; if (gradedata.n_GachaGrade == 9) { // 가챠 9등급 스페셜 앨범 지급 var tdata = table_album.Ins.Get_SpecialAlbum(SaveMgr.Ins.Get_SelectGirlID(), eCollectionMethod.Gacha); if (!SaveMgr.Ins.IsOpenAlbum(tdata)) { SaveMgr.Ins.Open_Album(tdata); SaveMgr.Ins.Save(); } } } public void OnClick_Skip() { if (!isGacha) return; StopAllCoroutines(); //AnimationState state = m_GachaAnim["Gacha"]; //state.normalizedTime = 0.8f; // 지점 이동 //m_GachaAnim.Sample(); // 즉시 반영 Init_GachaAnim(); StartCoroutine(GachaReward2()); ulong lastFrame = videoPlayer.frameCount - 1; videoPlayer.frame = (long)lastFrame; } public void OnClick_GachaRate() { Application.OpenURL("https://mergehero.notion.site/2a7e9deec1718038bae6dbce1a91f4c4"); } #region 동영상 public RawImage rawImage; public VideoPlayer videoPlayer; public GameObject[] gos_off_isPlaying; void Set_Video() { StartCoroutine(PrepareVideo()); } // 1. 비디오 준비 및 첫 프레임 보여주기 IEnumerator PrepareVideo() { videoPlayer.Prepare(); // 준비가 될 때까지 대기 while (!videoPlayer.isPrepared) yield return null; // RawImage에 비디오 텍스처 연결 rawImage.texture = videoPlayer.texture; // 첫 프레임을 그리기 위해 아주 잠깐 재생했다가 멈춤 videoPlayer.Play(); // 1프레임만 기다림 (화면에 그려질 시간 확보) yield return null; videoPlayer.Pause(); videoPlayer.time = 0; // 혹시 시간이 흘렀다면 0초로 강제 고정 } // 2. 외부에서 이 함수를 호출하여 재생 시작 public void PlayVideo() { if (videoPlayer.isPrepared) { DSUtil.InActivateGameObjects(gos_off_isPlaying); videoPlayer.Play(); StartCoroutine(GachaReward()); } } // 3. 동영상 재생이 끝났을 때 호출되는 이벤트 void OnVideoEnd(VideoPlayer vp) { DSUtil.ActivateGameObjects(gos_off_isPlaying); } // 4. 다시 첫 프레임으로 리셋하는 함수 void ResetToFirstFrame() { // Stop()을 쓰지 않고, 시간만 0으로 돌립니다. videoPlayer.time = 0; // 강제로 한 프레임을 업데이트하기 위해 Play -> 바로 Pause가 아니라 // VideoPlayer는 시간을 바꾸면 자동으로 그 프레임을 찾아서 보여줍니다. // 다만 반영될 시간을 조금 벌어주기 위해 코루틴을 씁니다. StartCoroutine(SeekAndPause()); } IEnumerator SeekAndPause() { // 시간을 0으로 맞춤 videoPlayer.time = 0; // 재생을 해서 0초의 화면을 갱신하게 함 videoPlayer.Play(); // 프레임이 갱신될 때까지 안전하게 대기 (0.1초 정도 여유를 둠) // 혹은 위의 방법1처럼 while(videoPlayer.frame < 1)을 써도 되지만, // 이미 재생했던 영상은 time=0으로 가면 frame이 초기화 안 될 수도 있어서 시간 대기가 안전할 수 있음 yield return new WaitForSeconds(0.1f); videoPlayer.Pause(); } #endregion }