using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using IVDataFormat; using Spine.Unity; using System; using System.Collections; using System.Collections.Generic; using System.Numerics; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.UI; using static CreatureBase; using Random = UnityEngine.Random; using Sequence = DG.Tweening.Sequence; using Vector2 = UnityEngine.Vector2; using Vector3 = UnityEngine.Vector3; // 전투 제어 매니저. public class BattleMgr : MonoSingleton { public enum TalkType { Summon, Attack, Die, } #region Const & Values private const int I_MonTypeNormal = 2; private const int I_MonTypeElite = 2; private const int I_MonTypeBoss = 1; private const int I_MonTypeBigBoss = 1; private const int I_SummonMin = 5; private const int I_SummonMax = 50; private const int I_SummonEliteMin = 1; private const int I_SummonEliteMax = 3; private const int I_ObjMonCnt = (I_MonTypeNormal * I_SummonMax) + (I_MonTypeElite * I_SummonEliteMax) + I_MonTypeBoss + I_MonTypeBigBoss; private const int I_ObjDamCnt = 200; private static readonly int _talkBoxSummonMaxCount = 2; private static readonly int _talkBoxAttackMaxCount = 4; private static readonly int _talkBoxDieMaxCount = 2; private static readonly Vector3 V3_CharOrigin = new Vector3(-0f, -2f, -12f); private static readonly Vector3 V3_CharPvp = new Vector3(-10f, 0f, 0f); private static readonly Vector3 V3_CharEnemyPvp = new Vector3(10f, 0f, 0f); private static readonly Vector3 V3_SummonMin = new Vector3(-20f, 6f, -40f);//5 -2 private static readonly Vector3 V3_SummonMax = new Vector3(20f, 8f, 40f);//13 6 private static readonly Vector3 V3_DgSummonMin = new Vector3(-20f, 5f, -16f); private static readonly Vector3 V3_DgSummonMax = new Vector3(20f, 13f, -16f); private static readonly Vector3[] V3_AddSummons = new Vector3[10] { new Vector3(-4.5f, 0f, 0f), new Vector3(-1.5f, 0f, 0f), new Vector3(1.5f, 0f, 0f), new Vector3(4.5f, 0f, 0f), new Vector3(-3f, 3f, 0f), new Vector3(0f, 3f, 0f), new Vector3(3f, 3f, 0f), new Vector3(-3f, -3f, 0f), new Vector3(0f, -3f, 0f), new Vector3(3f, -3f, 0f) }; private const float F_AddYCharHp = 2.5f; private const float F_AddYNormalHp = 2.2f; private const float F_AddYEliteHp = 3.5f; private const float F_AddYBossHp = 5.5f; private const float F_AddYAwakenStoneBossHp = 7f; private const float F_AddYCharTalk = 2f; private const float F_CharRangePvp = 3600000f; private const float F_MonRangeNormal = 2500000f; private const float F_MonRangeElite = 3000000f; private const float F_MonRangeBoss = 3500000f; #endregion Const & Values #region Battle UI [Header("Battle UI")] private Camera camMain; private Camera camUI; [SerializeField] private Transform trfStageInfo; private TextMeshProUGUI txtBattleStage; private TextMeshProUGUI txtBattleTime; private Button btnBattleRetry; private Image imgBattleRetry; [SerializeField] private Sprite sprBattleRetry, sprBattleGo, sprBossElite, sprBoss, sprAuto, sprAutoOff; [SerializeField] private TextMeshProUGUI txtRetry; private Image imgBattleWave; Image imgWaveBoss; GameObject goWaveBossArrow; Image[] imgWaveCapsule; GameObject[] goWaveCapsuleArrow; [Header("Pvp")] [SerializeField] private Transform trfPvp; private TextMeshProUGUI txtPvpTime; private Slider sldPvpMyHp, sldPvpEnemyHp; [Header("Skill")] [SerializeField] private Transform trfRB; private ButtonIV[] btnSkillPresets; private Button[] btnSkills; private GameObject[] goSkillEmptys; private Image[] imgSkills; private Image[] imgSkillBg; private Image[] imgSkillCovers; private TextMeshProUGUI[] txtSkills; private Image imgBtnAuto; private GameObject goAuto; [SerializeField] private TextMeshProUGUI[] txtTestDps; [SerializeField] private TextMeshProUGUI[] txtTestDpsDam; [SerializeField] private TextMeshProUGUI txtNormalAttackDpsDam; private BigInteger[] TestDps = new BigInteger[18]; private BigInteger TestNormalAttackDps = new BigInteger(); private int timeSec = 0; [Header("Battle Obj")] [SerializeField] private Canvas canvasUI; private Image screenCoverImg; private HpBar hpBarChar; private HpBar hpBarCharEnemy; private RectTransform trfHpBars; [SerializeField] private GameObject prfHpEnemy; private HpBar[] hpBarEnemies; private RectTransform trfDamages, trfCharDamages; [SerializeField] DamageIndicatorText prfDmgIndicator; private DamageIndicatorText[] dmgIndicatorsMon, dmgIndicatorsChar; private RectTransform trfTxts; private TalkBox talkBox; #endregion Battle UI #region UI Values private LayerMask layerMask; #endregion UI Values #region Battle Scene [Header("Battle Scene")] [SerializeField] private SpriteRenderer srBg; [SerializeField] StringList areaImgPathList; [SerializeField] ExtendSpriteRenderer backGroundRenderer; [SerializeField] private BoxCollider colBg; [SerializeField] private SpriteRenderer srSkillFade; private GameObject goBgEffect; [Header("Battle Scene Friendly")] [SerializeField] private Transform trfFriendlies; [SerializeField] private IVCharacter ivChar; private Transform trfChar; [SerializeField] private IVPet[] ivPets; [SerializeField] private IVGuardian ivGuardian; [SerializeField] private Light2D lightGlobal; [SerializeField] private Light2D lightChar; [SerializeField] private IVSummon[] ivsummons; [Header("Battle Scene Enemy Char")] [SerializeField] private IVCharacter ivCharEnemy; private Transform trfCharEnemy; [SerializeField] private IVPet[] ivPetsEnemy; [SerializeField] private IVGuardian ivGuardianEnemy; [SerializeField] private IVSummon[] ivsummonsEnemy; [Header("Battle Scene Enemy")] [SerializeField] private Transform trfEnemies; [SerializeField] private GameObject prfEnemy; private GameObject[] goMonsters; private Transform[] trfMonsters; private IVMonster[] ivMonsters; private HashSet battleEntities = new(); #endregion Battle Scene #region Battle Sound [Header("Battle Sound")] [SerializeField] private AudioSource asSummon; [SerializeField] private AudioSource asUnsummon; #endregion Battle Sound public bool doNotInterupt { get; set; } = false; #region Battle Effect [Header("Battle Scene Effect")] [SerializeField] private Transform trfEffects; [SerializeField] private ParticleSystem ptcLvUpChar; private Transform trfLvUpChar; [SerializeField] private ParticleSystem[] ptcGoldDrops; private Transform[] trfGoldDrops; private TweenerCore[] twcGoldDropMoves; private TweenerCore[] twcGoldDropScales; [SerializeField] private SerializedDictionary dicIvSkill = new SerializedDictionary(); [SerializeField] private SerializedDictionary dicIvSkillEnemy = new SerializedDictionary(); #endregion Battle Scene #region Battle Values private bool battlePause = false; public bool BattlePause { get => battlePause; set { if(battlePause != value) { battlePause = value; } } } private int iLoading = 1; private float fTick = 0f; private float fTickSec = 0f; private int iCosCloth = -1; private int iCosWp = -1; private int iCosClothEnemy = -1; private int iCosWpEnemy = -1; private Texture2D tx2dCloth = null; private Texture2D tx2dClothEnemy = null; private int[] iSkillIds; private float[] fSkillTimes = new float[0]; private float[] fSkillTicks = new float[0]; public bool IsOnAutoSkill { get; private set; } private bool bAutoSkillPrev = true; private Dictionary dicSkillIndex; private float[] fSkillEnemyTicks; private Dictionary dicSkillEnemyIndex; private AsyncOperationHandle[] handleSpines = new AsyncOperationHandle[8]; private int iStageTimeLeft = 90; private int iWave = 1; private int iTotalWave = 3; private bool bRetry = false; private bool bClear = false; private bool bChangeArea = false; private int iMonsterCount = 0; private float[] fMonSpeedN; private float[] fMonSpeedE; private float[] fMonSpeedB; private int[] iMonGroupN; private int[] iMonGroupE; private int[] iMonGroupB; private BigInteger biMonAtk; private BigInteger biMonHp; private Sequence seqDieStage = null; private Sequence seqChangeStage = null; private Sequence seqChangeArea = null; private Sequence seqChangeGameMod = null; private int iFadeCnt = 0; private bool BgAndCameraChange = false; private int useSkillid = -1; public enum BattleType { Stage = 0, Pvp = 9 } public BattleType CurrentBattleType { get; private set; } = BattleType.Stage; dPvpSpec specEnemy = null; // 내가 상대에게 준 총 데미지. private BigInteger biBattleDmg; // 상대가 나에게 준 총 데미지. private BigInteger biBattleDmgEnemy; #endregion Battle Values #region Level Up [SerializeField] LevelUpEffect levelUpEffect; public static void LevelUpEffectOn() { Instance.levelUpEffect.ShowLevelUp(2f); } #endregion #region Boss [SerializeField] SkeletonAnimation bossIncoming; #endregion #region Drop Item public enum DropItemKind { Gold, Exp, Box, ColorFlower, MemoryPiece, TradeEventCoin, RaiseEventCoin, RouletteEventCoin } [SerializeField] Transform trfDropItem; [SerializeField] DropItemObject prfDropItem; DropItemObject[] dropItemPool; int dropItemPoolCount = 100; int dropItemPoolCountNow = 0; int[] dropItemCount = new int[8]; Stack dropChestKey = new Stack(); #endregion #region StageSuccessOrFail [Header("Success & Fail")] [SerializeField] GameObject stageSuccessWindow; GoodsItem[] stageSuccessGoodsItem; [SerializeField] GameObject awakenSuccessWindow; TextMeshProUGUI awakenNumber; [SerializeField] Canvas canvasStageFail; GameObject groupButtonFailed; TextMeshProUGUI[] txtLevelUpKind; TextMeshProUGUI[] txtLevelUpGo; TextMeshProUGUI txtJellySad; TextMeshProUGUI txtFailed; TextMeshProUGUI txtClose; [SerializeField] GameObject[] canvasStageUnlock; TextMeshProUGUI[] txtUnlockTitle; TextMeshProUGUI[] txtUnlockExplain; TextMeshProUGUI[] txtBtnOk; TextMeshProUGUI[] txtBtnGo; DOTweenAnimation[] dotUnlock; [SerializeField] Sprite[] sprUnlockContent; #endregion #region Option Values [HideInInspector] public bool bOnSkillEffect; [HideInInspector] public bool bOnDamageText; #endregion Option Values [SerializeField] List gameMods; GameMod currentGameMod; #region Update private void Update() { if (BattlePause) return; if (currentGameMod is null) { UpdateModTime(); } UpdateSkill(); } // 현재 모드 타임 아웃 체크 private void UpdateModTime() { fTickSec += Time.deltaTime; if (fTickSec >= 1f) { fTickSec -= 1f; iStageTimeLeft--; if (CurrentBattleType == BattleType.Pvp) { txtPvpTime.text = iStageTimeLeft.ToString(); if (iStageTimeLeft <= 0) { EndPvp(); } } else { txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft); if (iStageTimeLeft <= 0) { ivChar.ChangeState(eState.die); } } } } // 자동 스킬 쿨타임 감소 및 자동 사용 체크 시 시전 대기 스택에 넣기 private void UpdateSkill() { fTick += Time.deltaTime; if (fTick >= 0.1f) { fTick -= 0.1f; for (int i = 0; i < fSkillTicks.Length; i++) { if (iSkillIds[i] < 0) continue; if (fSkillTicks[i] >= 0f) { fSkillTicks[i] -= 0.1f; SetSkillUi(i); if (fSkillTicks[i] <= 0f) { if (IsOnAutoSkill) ivChar.AddSkillAvail(iSkillIds[i]); } } } if (CurrentBattleType == BattleType.Pvp) { for (int i = 0; i < fSkillEnemyTicks.Length; i++) { if (specEnemy.skillPreset[i] < 0) continue; if (fSkillEnemyTicks[i] >= 0f) { fSkillEnemyTicks[i] -= 0.1f; if (fSkillEnemyTicks[i] <= 0f) { ivCharEnemy.AddSkillAvail(specEnemy.skillPreset[i]); } } } } } } #endregion #region Init public static void SLocalize() => Instance.Localize(); private void Localize() { txtLevelUpKind[0].text = FormatString.StringFormat("{0}", LocalizationText.GetText("recommand_grow")); txtLevelUpKind[1].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("bag_weapon"), LocalizationText.GetText("all_enhance")); txtLevelUpKind[2].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("skill_title"), LocalizationText.GetText("all_enhance")); txtLevelUpKind[3].text = FormatString.StringFormat("{0} {1}", LocalizationText.GetText("pet_title"), LocalizationText.GetText("all_enhance")); for (int i = 0; i < 5; i++) { txtLevelUpGo[i].text = LocalizationText.GetText("shortcut"); } txtJellySad.text = LocalizationText.GetText("stage_fail_jelly_dialogue"); txtFailed.text = LocalizationText.GetText("fail_recommand"); txtClose.text = LocalizationText.GetText("click_to_close"); SetDpsSkill(); SetRetry(); bRetry = DataHandler.PlayData.stageRepeat; txtUnlockTitle = new TextMeshProUGUI[canvasStageUnlock.Length]; txtUnlockExplain = new TextMeshProUGUI[canvasStageUnlock.Length]; txtBtnOk = new TextMeshProUGUI[canvasStageUnlock.Length]; txtBtnGo = new TextMeshProUGUI[canvasStageUnlock.Length]; dotUnlock = new DOTweenAnimation[canvasStageUnlock.Length]; for (int i = 0; i < canvasStageUnlock.Length; i++) { txtUnlockTitle[i] = canvasStageUnlock[i].transform.Find("txtTitle").GetComponent(); txtUnlockExplain[i] = canvasStageUnlock[i].transform.Find("txtExplain").GetComponent(); txtBtnOk[i] = canvasStageUnlock[i].transform.Find("btnOk").transform.Find("txt").GetComponent(); txtBtnGo[i] = canvasStageUnlock[i].transform.Find("btnGo").transform.Find("txt").GetComponent(); dotUnlock[i] = canvasStageUnlock[i].GetComponent(); txtBtnOk[i].text = LocalizationText.GetText("all_confirm"); txtBtnGo[i].text = LocalizationText.GetText("mission_go"); } txtUnlockTitle[0].text = LocalizationText.GetText("unlock_gold_dg"); txtUnlockExplain[0].text = LocalizationText.GetText("unlock_gold_explain"); txtUnlockTitle[1].text = LocalizationText.GetText("unlock_enhancestone_dg"); txtUnlockExplain[1].text = LocalizationText.GetText("unlock_enhancestone_explain"); txtUnlockTitle[2].text = LocalizationText.GetText("unlock_pet_dg"); txtUnlockExplain[2].text = LocalizationText.GetText("unlock_pet_explain"); txtUnlockTitle[3].text = LocalizationText.GetText("unlock_awakenstone_dg"); txtUnlockExplain[3].text = LocalizationText.GetText("unlock_awakenstone_explain"); txtUnlockTitle[4].text = LocalizationText.GetText("unlock_awaken_dg"); txtUnlockExplain[4].text = LocalizationText.GetText("unlock_awaken_explain"); txtUnlockTitle[5].text = LocalizationText.GetText("unlock_acc"); txtUnlockExplain[5].text = LocalizationText.GetText("unlock_acc_explain"); txtUnlockTitle[6].text = LocalizationText.GetText("unlock_treasure"); txtUnlockExplain[6].text = LocalizationText.GetText("unlock_treasure_explain"); } // 클래스 초기화. 게임 처음 시작 시 호출. public void Init(Camera camui) { IVCameraController.SSetTrace(false); camMain = Camera.main; camUI = camui; InitObject(); CustomizeMgr.Instance.InitSkin(); iCosWp = DataHandler.PlayEquipCostume.weaponId; iCosCloth = DataHandler.PlayEquipCostume.outfitId; ivChar.SetSkin(iCosCloth, iCosWp); SetEnemyCostume(DataHandler.PlayEquipCostume.weaponId, DataHandler.PlayEquipCostume.outfitId); iCosClothEnemy = -1; iCosWpEnemy = -1; ivChar.gameObject.SetActive(false); ivCharEnemy.gameObject.SetActive(false); GamePlayBuffMgr.Instance.OnChanged -= OnChangedBuffList; GamePlayBuffMgr.Instance.OnChanged += OnChangedBuffList; } private void OnChangedBuffList(BuffData buffData, bool added) { BuffMgr.Instance.CalcAllStat(); ivChar.RefreshStat(); RecalcAllSkillCool(); } // 스테이지 초기화. 게임 시작시 전투 시작해도 되는 타이밍에 호출(다른 초기화 완료 후). public void InitStage() { iStageTimeLeft = DataHandler.Const.stageTimeout; txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft); iWave = 1; iTotalWave = GetWaveTotal(); SetWaveCapsule(iTotalWave); GetStageItemAndGetPercent(); SetStageAreaWave(DataHandler.PlayData.curStage, iWave); SetRetry(); var seqStartStage = DOTween.Sequence() .SetUpdate(false) .AppendCallback(() => { screenCoverImg.color = Color.black; screenCoverImg.gameObject.SetActive(true); IVCameraController.SMoveCamera(V3_CharOrigin); iStageTimeLeft = DataHandler.Const.stageTimeout; txtBattleTime.text = FormatString.TextTimeSec(iStageTimeLeft); iWave = 1; iTotalWave = GetWaveTotal(); SetWaveCapsule(iTotalWave); SetBg(); InitMonArea(); SetStageAreaWave(DataHandler.PlayData.curStage, iWave); }) .Append(screenCoverImg.DOFade(0f, 1f)) .AppendCallback(() => { screenCoverImg.gameObject.SetActive(false); ivChar.ResetDebuff(); ivChar.SetStatus(BuffMgr.Instance.GetCharAtk(), BuffMgr.Instance.GetCharHp(), BuffMgr.Instance.GetCharCrtDam(), BuffMgr.Instance.GetCharCrtRate(), BuffMgr.Instance.GetCharMov(), BuffMgr.Instance.GetCharSpd(), GameProperty.Instance.PlayerCharacterAttackRange); ivChar.Summon(new Vector3(10000f, 10000f, 0f), true); StartCoroutine(nameof(LightCharOn)); SkillFade(false, true); }) .AppendInterval(0.3f) .AppendCallback(() => { ivChar.transform.position = V3_CharOrigin; SoundMgr.Instance.PlaySfx(asSummon.clip); }) .AppendInterval(0.5f) .AppendCallback(() => { ShowTalkBox(TalkType.Summon); SummonMonStage(); IVCameraController.SSetTrace(true); BattlePause = false; for (int i = 0; i < ivPets.Length; i++) { ivPets[i].Summon(); } ivGuardian.Summon(); }) .Play(); } // 전투 오브젝트 초기화. 클래스 초기화(SInit)에서 호출. private void InitObject() { layerMask = LayerMask.GetMask("BG", "Character", "Effect"); #region Char trfChar = ivChar.transform; IVCameraController.SSetTarget(trfChar); Transform trfbattleui = canvasUI.transform; screenCoverImg = trfbattleui.Find("cover").GetComponent(); trfHpBars = trfbattleui.Find("HpBars").GetComponent(); hpBarChar = trfHpBars.GetChild(0).GetComponent(); trfDamages = trfbattleui.Find("Damages").GetComponent(); trfCharDamages = trfbattleui.Find("CharDamages").GetComponent(); trfTxts = trfbattleui.Find("Txts").GetComponent(); talkBox = trfTxts.GetChild(0).GetComponent(); hpBarChar.SetCameraTarget(camMain, camUI, trfHpBars, ivChar.transform, F_AddYCharHp); talkBox.SetCameraTarget(camMain, camUI, trfTxts, ivChar.transform, F_AddYCharTalk); levelUpEffect.SetCameraTarget(camMain, camUI, trfTxts, ivChar.transform, 4f); ivChar.Init(); ivChar.SetHpbar(hpBarChar); ivChar.SetFriendly(true); ivChar.SetClassIndex(CreatureBase.eCreatureClass.character, 0); for(int i = 0; i < ivsummons.Length; i++) ivsummons[i].SetInit(this); for(int i = 0; i < ivPets.Length; i++) { ivPets[i].Init(); ivPets[i].OffPet(); } ivGuardian.Init(); ivGuardian.OffGuardian(); #endregion Char #region Enemy Char trfCharEnemy = ivCharEnemy.transform; hpBarCharEnemy = trfHpBars.GetChild(1).GetComponent(); hpBarCharEnemy.SetCameraTarget(camMain, camUI, trfHpBars, ivCharEnemy.transform, F_AddYCharHp); ivCharEnemy.Init(); ivCharEnemy.SetHpbar(hpBarCharEnemy); ivCharEnemy.SetFriendly(false); ivCharEnemy.SetClassIndex(CreatureBase.eCreatureClass.charEnemy, 0); for(int i = 0; i < ivsummons.Length; i++) ivsummonsEnemy[i].SetInit(this); for(int i = 0; i < ivPetsEnemy.Length; i++) { ivPetsEnemy[i].Init(); ivPetsEnemy[i].OffPet(); } ivGuardianEnemy.Init(); ivGuardianEnemy.OffGuardian(); #endregion Enemy Char #region Monsters hpBarEnemies = new HpBar[I_ObjMonCnt]; goMonsters = new GameObject[I_ObjMonCnt]; trfMonsters = new Transform[I_ObjMonCnt]; ivMonsters = new IVMonster[I_ObjMonCnt]; int inormalmax = I_MonTypeNormal * I_SummonMax; int ielitemax = inormalmax + (I_MonTypeElite * I_SummonEliteMax); int ibossmax = inormalmax + (I_MonTypeElite * I_SummonEliteMax) + I_MonTypeBoss; for (int i = 0; i < I_ObjMonCnt; i++) { goMonsters[i] = Instantiate(prfEnemy, trfEnemies); goMonsters[i].name = FormatString.CombineAllString("enemy", i.ToString()); trfMonsters[i] = goMonsters[i].transform; ivMonsters[i] = goMonsters[i].GetComponent(); GameObject gohpbar = Instantiate(prfHpEnemy, trfHpBars); gohpbar.transform.localScale = Vector3.one; gohpbar.name = FormatString.CombineAllString("hpbar", i.ToString()); hpBarEnemies[i] = gohpbar.GetComponent(); ivMonsters[i].Init(); ivMonsters[i].SetHpbar(hpBarEnemies[i]); if (i < inormalmax) { hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYNormalHp); ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.normal, i); } else if (i < ielitemax) { hpBarEnemies[i].SetCameraTarget(camMain, camUI, trfHpBars, trfMonsters[i], F_AddYEliteHp); ivMonsters[i].SetClassIndex(CreatureBase.eCreatureClass.elite, i); } else if(i[ptcGoldDrops.Length]; twcGoldDropScales = new TweenerCore[ptcGoldDrops.Length]; for (int i = 0; i < ptcGoldDrops.Length; i++) { trfGoldDrops[i] = ptcGoldDrops[i].transform; twcGoldDropMoves[i] = trfGoldDrops[i].DOMove(trfChar.position, 0.3f).SetEase(Ease.InQuad) .OnComplete(() => { ptcGoldDrops[i].Stop(); trfGoldDrops[i].gameObject.SetActive(false); }).SetAutoKill(false).Pause(); twcGoldDropScales[i] = trfGoldDrops[i].DOScale(Global.V3_001, 0.25f).SetEase(Ease.InQuad).SetAutoKill(false).Pause(); } foreach (var item in dicIvSkill) item.Value.Init(this); foreach (var item in dicIvSkillEnemy) item.Value.Init(this); #endregion Effects #region Drop Item //poolCount 는 변수목록에 있음 dropItemPool = new DropItemObject[dropItemPoolCount]; for (int i = 0; i < dropItemPoolCount; i++) { dropItemPool[i] = Instantiate(prfDropItem, trfDropItem); dropItemPool[i].gameObject.SetActive(false); } #endregion #region UI int ipresetlen = DataHandler.PlayData.skillPresets.Length; int iskilllen = DataHandler.PlayData.skillPresets[0].Length; btnSkillPresets = new ButtonIV[ipresetlen]; btnSkills = new Button[iskilllen]; goSkillEmptys = new GameObject[iskilllen]; imgSkills = new Image[iskilllen]; imgSkillBg = new Image[iskilllen]; imgSkillCovers = new Image[iskilllen]; txtSkills = new TextMeshProUGUI[iskilllen]; iSkillIds = new int[iskilllen]; fSkillTimes = new float[iskilllen]; fSkillTicks = new float[iskilllen]; dicSkillIndex = new Dictionary(); fSkillEnemyTicks = new float[iskilllen]; dicSkillEnemyIndex = new Dictionary(); int irblen = trfRB.childCount; for (int i = 0; i < irblen; i++) { int index = i; if (i < ipresetlen) { btnSkillPresets[index] = trfRB.GetChild(i).GetComponent(); continue; } index -= ipresetlen; if (index >= iskilllen) break; btnSkills[index] = trfRB.GetChild(i).GetComponent