using UnityEngine; using UnityEngine.UI; using DG.Tweening; using TMPro; using System.Collections.Generic; using UnityEngine.SceneManagement; using DarkTonic.MasterAudio; using System.Collections; #if UNITY_EDITOR // PackageManager °ü·Ã ÄÚµå #endif public class BattleManager : MonoBehaviour { public GameObject HeroUnit; public Transform[] MonsterPositions = new Transform[3]; public GameObject HitEffectPrefab; public GameObject MissPrefab; public GameObject NumberPrefab; public GameObject CriticalPrefab; public TextMeshProUGUI stageClearText; public Image darkPanel; // ´ÙÅ© Ŀư À̹ÌÁö¸¦ ´ãÀ» º¯¼ö public float CriticalRate; // Ä¡¸íŸ È®·ü(10000ºÐÀ²) public float CriticalDamage; // Ä¡¸íŸ ¹èÀ²(10000ºÐÀ²) public int HeroDamag; // ¿µ¿õ °ø°Ý·Â private List aliveMonsters = new List(); private bool stageCleared = false; private bool isHeroAttacking = false; public string playlistName = "Bgm"; // ½ºÇÁ¶óÀÌÆ® ·£´õ·¯ ¹è¿­ Ãß°¡ private SpriteRenderer[] spriteRenderers; private void Start() { // óÀ½¿¡ ¸ðµç ¸ó½ºÅ͸¦ »ýÁ¸ ¸ó½ºÅÍ ¸®½ºÆ®¿¡ Ãß°¡ foreach (Transform monsterPos in MonsterPositions) { aliveMonsters.Add(monsterPos); } // NumberPrefabÀÇ ÀÚ½Ä ¿ÀºêÁ§Æ® ¼ö¸¦ °¡Á®¿É´Ï´Ù. int childCount = NumberPrefab.transform.childCount; // ½ºÇÁ¶óÀÌÆ® ·£´õ·¯ ¹è¿­ ÃʱâÈ­ spriteRenderers = new SpriteRenderer[childCount]; // °¢ ÀÚ½Ä ¿ÀºêÁ§Æ®ÀÇ ½ºÇÁ¶óÀÌÆ® ·£´õ·¯ ÄÄÆ÷³ÍÆ®¸¦ ¹è¿­¿¡ ÇÒ´ç for (int i = 0; i < childCount; i++) { Transform child = NumberPrefab.transform.GetChild(i); SpriteRenderer spriteRenderer = child.GetComponent(); if (spriteRenderer != null) { spriteRenderers[i] = spriteRenderer; } else { Debug.LogError("SpriteRenderer component not found on child " + i + " of NumberPrefab."); } } MasterAudio.PlaylistsMuted = true; MasterAudio.PlaySound("BGM_DAILYDUNGEON", 0.7f); } public void HeroAttack() { if (aliveMonsters.Count > 0 && !isHeroAttacking) { isHeroAttacking = true; HeroUnit.SetActive(true); // ¿µ¿õÀÇ °ø°Ý ¾Ö´Ï¸ÞÀÌ¼Ç Sequence attackSequence = DOTween.Sequence(); attackSequence.Append(HeroUnit.transform.DOLocalMoveY(-700, 0.25f).SetEase(Ease.OutCubic)); attackSequence.AppendCallback(() => { // °ø°Ý ¾Ö´Ï¸ÞÀ̼ÇÀÌ ³¡³ª¸é ¸ó½ºÅÍ¿¡°Ô ÇÇÇØ¸¦ ÀÔÈü´Ï´Ù. DealDamageToMonster(); }); attackSequence.Append(HeroUnit.transform.DOLocalMoveY(-1500, 0.15f).SetEase(Ease.OutCubic)); attackSequence.OnComplete(() => { // ¾Ö´Ï¸ÞÀÌ¼Ç Á¾·á ÈÄ °ø°ÝÀ» Çã¿ë isHeroAttacking = false; HeroUnit.SetActive(false); }); } } private void DealDamageToMonster() { if (aliveMonsters.Count > 0) { int randomMonsterIndex = Random.Range(0, aliveMonsters.Count); Transform targetMonster = aliveMonsters[randomMonsterIndex]; float randomNumber = Random.Range(0, HeroDamag); // 0ºÎÅÍ ¿µ¿õ °ø°Ý·Â¸¸Å­ÀÇ ÇÇÇØ¸¦ Àû¿ë // ·£´ý °ªÀ» »ý¼ºÇÏ¿© Å©¸®Æ¼Äà Ȯ·ü°ú ºñ±³ float randomValue = Random.Range(0, 10000); // 0ºÎÅÍ 9999±îÁöÀÇ ·£´ý °ª bool isCritical = randomValue<= CriticalRate; int resultNumber = 0; int randomSoundIndex = Random.Range(1, 4); // 1ºÎÅÍ 3±îÁöÀÇ ·£´ýÇÑ Á¤¼ö »ý¼º string soundName = "Hot_Type2_" + randomSoundIndex.ToString(); // »ç¿îµå À̸§ »ý¼º MasterAudio.PlaySound(soundName, 0.7f, null); int randomVoiceIndex = Random.Range(1, 13); // 1ºÎÅÍ 12±îÁöÀÇ ·£´ýÇÑ Á¤¼ö »ý¼º string voiceName = "Voice_HERO_01_Combo_1_" + randomVoiceIndex.ToString(); // »ç¿îµå À̸§ »ý¼º MasterAudio.PlaySound(voiceName, 0.7f, null); if (isCritical) { resultNumber = Mathf.RoundToInt((randomNumber * CriticalDamage) / 10000f); } else { resultNumber = (int)randomNumber; } // HitEffectPrefab ¿ÀºêÁ§Æ®¸¦ º¹Á¦ÇÏ¿© ÀÌÆåÆ®¸¦ Ç¥½ÃÇÒ ¿ÀºêÁ§Æ® »ý¼º GameObject hitEffectPosition = Instantiate(HitEffectPrefab, targetMonster.position, Quaternion.identity); hitEffectPosition.SetActive(true); Destroy(hitEffectPosition, 0.5f); // ÀÏÁ¤ ½Ã°£ ÈÄ¿¡ Á¦°Å if (resultNumber == 0) { // ¸ó½ºÅÍ À§Ä¡·Î ¹Ì½º ÀÌÆåÆ® ¹ß»ý ShowMissDamage(targetMonster.position + new Vector3(0, 1.4f, 0), targetMonster); } else { ShowNumberDamage(targetMonster.position + new Vector3(0, 1.4f, 0), targetMonster, resultNumber, isCritical); // HitEffectPrefab ¿ÀºêÁ§Æ®¸¦ º¹Á¦ÇÏ¿© ÀÌÆåÆ®¸¦ Ç¥½ÃÇÒ ¿ÀºêÁ§Æ® »ý¼º } } } private void ShowMissDamage(Vector3 monsterPosition, Transform targetMonster) { // ¸ó½ºÅÍ À§Ä¡·Î ¹Ì½º ÀÌÆåÆ® »ý¼º GameObject missObject = Instantiate(MissPrefab, monsterPosition, Quaternion.identity); missObject.SetActive(true); // ¹Ì½º ¾Ö´Ï¸ÞÀÌ¼Ç missObject.transform.localScale = Vector3.one * 1.5f; missObject.transform.DOScale(Vector3.one * 0.3f, 0.4f).SetEase(Ease.OutCubic); missObject.transform.DOMoveY(missObject.transform.position.y + 1, 0.5f).SetEase(Ease.OutCubic).OnComplete(() => { Destroy(missObject); }); } private void ShowCriEffect(Vector3 monsterPosition, Transform targetMonster) { GameObject CriObject = Instantiate(CriticalPrefab, monsterPosition, Quaternion.identity); CriObject.SetActive(true); // Å©¸® ¾Ö´Ï¸ÞÀÌ¼Ç CriObject.transform.localScale = Vector3.one * 1.5f; CriObject.transform.DOScale(Vector3.one * 0.3f, 0.4f).SetEase(Ease.OutCubic); CriObject.transform.DOMoveY(CriObject.transform.position.y + 1, 0.5f).SetEase(Ease.OutCubic).OnComplete(() => { Destroy(CriObject); }); } private void ShowNumberDamage(Vector3 monsterPosition, Transform targetMonster, int damage, bool isCritical) { // ¶³¸² È¿°ú Ãß°¡ targetMonster.DOPunchPosition(new Vector3(10, 0, 0), 0.2f); // damage¸¦ ¹®ÀÚ¿­·Î º¯È¯ string damageString = damage.ToString(); // ¼­·Î ¶³¾îÁø À§Ä¡ Á¶Àý°ª float xOffset = 0; if (isCritical) { xOffset+=2.3f; } else { xOffset += 1.1f; } float totalWidth = ((damageString.Length-1) * xOffset); // Àüü ³Êºñ // ºÎ¸ð ¿ÀºêÁ§Æ® »ý¼º GameObject digitObject = new GameObject("HitNumber"); // ¼ýÀÚ À§Ä¡¸¦ monsterPositionÀ» ±âÁØÀ¸·Î ¼³Á¤ (·ÎÄà Æ÷Áö¼Ç) digitObject.transform.localPosition = new Vector3(monsterPosition.x, monsterPosition.y - 2f, monsterPosition.z); // ¾Ö´Ï¸ÞÀÌ¼Ç ¹× À§Ä¡ ¼³Á¤ for (int i = 0; i < damageString.Length; i++) { int digit = int.Parse(damageString[i].ToString()); // ÀÚ¸´¼ö¸¦ ÃßÃâ if (digit >= 0 && digit < spriteRenderers.Length) { if (isCritical) { digit += 10; } // ¼ýÀÚ ½ºÇÁ¶óÀÌÆ® ·£´õ·¯ ¼³Á¤ SpriteRenderer digitSpriteRenderer = spriteRenderers[digit]; // ¼ýÀÚ ½ºÇÁ¶óÀÌÆ® º¹Á¦ GameObject digitImageObject = new GameObject("DigitImage"); // »õ °ÔÀÓ ¿ÀºêÁ§Æ® »ý¼º //digitImageObject.transform.position = digitObject.transform.position; // ½ºÇÁ¶óÀÌÆ® ·£´õ·¯ Ãß°¡ ¹× ¼³Á¤ SpriteRenderer newRenderer = digitImageObject.AddComponent(); newRenderer.sprite = digitSpriteRenderer.sprite; // Order °ªÀ» 300À¸·Î ¼³Á¤ newRenderer.sortingOrder = 300; // x À§Ä¡ Á¶ÀýÇÏ¿© Áß¾Ó Á¤·ÄµÈ »óÅ¿¡¼­ ¹èÄ¡ float xPos = -totalWidth / 2 + i * xOffset; digitImageObject.transform.localPosition = new Vector3(xPos, 0, 0); // ½ºÄÉÀÏ Á¶Àý (Å©±â µ¿ÀÏÇϰÔ) digitImageObject.transform.localScale = Vector3.one * 1.0f; // ºÎ¸ð ¼³Á¤ digitImageObject.transform.SetParent(digitObject.transform); } else { Debug.LogWarning("Digit out of range: " + digit); } } if (isCritical) { ShowCriEffect(targetMonster.position + new Vector3(0, 1.8f, 0), targetMonster); digitObject.transform.localScale = Vector3.one * 0.5f; // Å©±â ¼³Á¤ digitObject.transform.DOScale(Vector3.one * 0.2f, 0.3f).SetEase(Ease.OutCubic); digitObject.transform.DOMoveY(digitObject.transform.position.y + 2, 0.5f).SetEase(Ease.OutCubic).OnComplete(() => { Destroy(digitObject); // ½ºÇÁ¶óÀÌÆ® ·£´õ·¯¸¦ °¡Áø °ÔÀÓ ¿ÀºêÁ§Æ®¸¦ Á¦°ÅÇÕ´Ï´Ù. }); } else { // digitObject¸¦ ±âÁØÀ¸·Î ¾Ö´Ï¸ÞÀÌ¼Ç ¼³Á¤ digitObject.transform.localScale = Vector3.one * 0.5f; // Å©±â ¼³Á¤ digitObject.transform.DOScale(Vector3.one * 0.3f, 0.3f).SetEase(Ease.OutCubic); digitObject.transform.DOMoveY(digitObject.transform.position.y + 2, 0.5f).SetEase(Ease.OutCubic).OnComplete(() => { Destroy(digitObject); // ½ºÇÁ¶óÀÌÆ® ·£´õ·¯¸¦ °¡Áø °ÔÀÓ ¿ÀºêÁ§Æ®¸¦ Á¦°ÅÇÕ´Ï´Ù. }); } // ¸ó½ºÅÍÀÇ HP °ÔÀÌÁö °¨¼Ò ó¸® MonsterHealth monsterHealth = targetMonster.GetComponentInChildren(); if (monsterHealth != null && !monsterHealth.IsDead) { monsterHealth.TakeDamage(damage); // damage ¸¸Å­ °¨¼Ò // ¸¸¾à ¸ó½ºÅÍÀÇ HP°¡ 0 ÀÌÇϸé if (monsterHealth.CurrentHealth <= 0) { // ¸ó½ºÅ͸¦ ¸®½ºÆ®¿¡¼­ Á¦°Å aliveMonsters.Remove(targetMonster); // ³²Àº ¸ó½ºÅͰ¡ ¾øÀ¸¸é StageClear È¿°ú Ç¥½Ã if (aliveMonsters.Count == 0 && !stageCleared) { stageCleared = true; MasterAudio.StopAllOfSound("BGM_DAILYDUNGEON"); MasterAudio.PlaySound("BGM_VAILAGE", 0.7f); ShowStageClearAnimation(); } } } } private void ShowStageClearAnimation() { // ÅØ½ºÆ® Ȱ¼ºÈ­ ¹× ÃʱâÈ­ stageClearText.gameObject.SetActive(true); HeroUnit.SetActive(false); stageClearText.transform.localScale = Vector3.zero; // Scale ¾Ö´Ï¸ÞÀÌ¼Ç stageClearText.transform.DOScale(Vector3.one, 0.5f).SetEase(Ease.OutBack).OnComplete(() => { // ÅØ½ºÆ® Èçµé¸² ¾Ö´Ï¸ÞÀÌ¼Ç stageClearText.transform.DOShakePosition(1.0f, new Vector3(0, 10, 0), 10, 90, false, true).OnComplete(() => { // ÅØ½ºÆ® ÆäÀÌµå ¾Æ¿ô ¾Ö´Ï¸ÞÀÌ¼Ç CanvasGroup canvasGroup = stageClearText.GetComponent(); canvasGroup.DOFade(0, 0.5f).OnComplete(() => { // ´ÙÅ© Ŀư À̹ÌÁö Ȱ¼ºÈ­ darkPanel.gameObject.SetActive(true); // ¾îµÎ¿ò È¿°ú ¾Ö´Ï¸ÞÀÌ¼Ç (Åõ¸íµµ¸¦ 0¿¡¼­ 1·Î º¯°æ) DOVirtual.Float(0, 1.0f, 1.0f, (fadeValue) => { darkPanel.color = new Color(0, 0, 0, fadeValue); }).OnComplete(() => { // ´ÙÀ½ ¾À È£Ãâ MasterAudio.PlaySound("BGM_VAILAGE", 0); MasterAudio.PlaylistsMuted = false; SceneManager.LoadScene(4); }); }); }); }); } }