본문 바로가기
게임 개발

[Unity] 디펜스게임 개발 - 분열 스킬

by chobbo 2024. 7. 31.

Split Skill 스크립트

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class SplitSkill : OneTimeSkill
{
    [Header("# Split Skill")]
    [SerializeField] private int splitEnemyCount;
    [SerializeField] private float moveDelay;

    [Header("# Split Skill Effect")]
    [SerializeField] private GameObject splitEffect;
    [SerializeField] private TextMeshProUGUI splitTXT;

    private Coroutine splitCoroutine;
    private WaitForSeconds moveDelayWaitForSeconds;
    private readonly List<Boss_Water> splitBossList = new List<Boss_Water>();
    private Boss_Water waterBoss;

    private void Start()
    {
        if(waterBoss == null)
            waterBoss = boss as Boss_Water;
        if(moveDelayWaitForSeconds == null)
            moveDelayWaitForSeconds = new WaitForSeconds(moveDelay);
    }

    public override void UseSkill()
    {
        waterBoss.StateMachine.ChangeState(waterBoss.StateMachine.SkillState);
        if(splitCoroutine!= null) 
            StopCoroutine(splitCoroutine);
        splitCoroutine = StartCoroutine(SpawnSplitEnemy());
    }

    public override void EndSkill()
    {
        base.EndSkill();
        if (splitCoroutine != null)
            StopCoroutine(splitCoroutine);

        // 분열 스킬을 사용한 보스가 MoveDelay 도중 죽었을 경우 예외처리
        foreach (Boss_Water splitBoss in splitBossList)
        {
            if (splitBoss != null)
                splitBoss.StateMachine.ChangeState(splitBoss.StateMachine.MoveState);
        }
        DisableUI();
    }

    private IEnumerator SpawnSplitEnemy()
    {
        InitUI();
        splitEffect.SetActive(true);

        splitBossList.Clear();
        splitBossList.Add(waterBoss); 

        waterBoss.Split();
        waterBoss.HealthSystem.InitHealthSystem(waterBoss.HealthSystem.GetCurHealth());

        for (int i = 0; i < splitEnemyCount - 1; i++)
        {
            Boss_Water splitBoss = GameManager.Instance.Pool.SpawnFromPool((int)EEnemyType.Boss).ReturnMyComponent<Boss_Water>();
            if (splitBoss != null)
            {
                GameManager.Instance.Stage.SpawnEnemyList.Add(splitBoss);
                splitBossList.Add(splitBoss);

                // 생성 위치 설정
                splitBoss.transform.position = transform.position + transform.forward * -0.4f * (i + 1);
                // 크기 설정
                splitBoss.transform.localScale = waterBoss.transform.localScale;
                //목표 웨이포인트 - 기준 보스의 웨이포인트
                splitBoss.SetTargetIndex(waterBoss.TargetIndex);
                // 체력 설정 - 기준 보스의 현재 체력
                splitBoss.HealthSystem.InitHealthSystem(waterBoss.HealthSystem.GetCurHealth());
            }
        }

        // 분열된 보스 초기화
        foreach (Boss_Water splitBoss in splitBossList)
        {
            if (splitBoss != null)
            {
                splitBoss.SplitBossInit(waterBoss.EnemyData, waterBoss.Stat, waterBoss.CurSplitCount, waterBoss.uI_BlockUnitSpawn);
                // 분열 중일 때 무적
                splitBoss.HealthSystem.ChangeInvincibility(true);
            } 
        }

        yield return moveDelayWaitForSeconds;

        // 분열된 보스 움직이기
        foreach (Boss_Water splitBoss in splitBossList)
        {
            if(splitBoss != null)
            {
                splitBoss.StateMachine.ChangeState(splitBoss.StateMachine.MoveState);
                splitBoss.HealthSystem.ChangeInvincibility(false);
            }
        }

        DisableUI();
        splitEffect.SetActive(false);
        waterBoss.SkillHandler.FinishSkillCast();
    }

    private void InitUI()
    {
        if (splitTXT != null)
        {
            splitTXT.gameObject.SetActive(true);
            splitTXT.transform.SetParent(UIManager.Instance.UI_EnemyHpBar.transform);
            splitTXT.transform.position = transform.position + Vector3.up *3f;
            splitTXT.transform.rotation = Quaternion.Euler(60,0, 0);
            splitTXT.text = $"분열!";

            // 닷트윈 
            float targetY = splitTXT.transform.position.y + 1f;
            splitTXT.transform.DOMoveY(targetY, moveDelay).SetEase(Ease.OutQuad);
        }
    }

    private void DisableUI()
    {
        if(splitTXT != null)
        {
            splitTXT.gameObject.SetActive(false);
            splitTXT.transform.SetParent(transform);
        }
    }
}