OneShotOneKill/Assets/Script/InGame/Mgr/ProjectileMgr.cs

132 lines
4.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ProjectileMgr : MonoBehaviourSingletonTemplate<ProjectileMgr>
{
Dictionary<string, List<ProjectileBase>> dic_projectile = new Dictionary<string, List<ProjectileBase>>();
public bool LoadComplete;
protected override void Awake()
{
base.Awake();
DontDestroyOnLoad(transform.parent.gameObject);
}
public void AllOff()
{
#if UNITY_EDITOR
if (MyValue.m_MyStageData.m_EnterType == eStageEnterType.Tool || MyValue.m_MyStageData.m_EnterType == eStageEnterType.Tool_Mob)
return;
#endif
foreach (var item in dic_projectile)
for (int i = 0; i < item.Value.Count; i++)
item.Value[i].gameObject.SetActive(false);
}
public IEnumerator Co_Load(Action<float> addslidevalue)
{
LoadComplete = false;
var lst = table_projectile.Ins.Get_DataList();
int totalCount = lst.Count;
// 슬라이더 35% 사용
float add1value = 0.35f / totalCount;
const int batchSize = 10; // 한 번에 10개씩 로드
for (int batchStart = 0; batchStart < totalCount; batchStart += batchSize)
{
// 🔹 현재 배치의 끝 인덱스
int batchEnd = Mathf.Min(batchStart + batchSize, totalCount);
// 🔹 이 배치에서 비동기로 로드할 코루틴 리스트
List<Coroutine> coroutines = new List<Coroutine>();
// 🔹 병렬로 10개 로드 시작
for (int i = batchStart; i < batchEnd; i++)
{
var data = lst[i];
if (!dic_projectile.ContainsKey(data.s_Projectile))
dic_projectile.Add(data.s_Projectile, new List<ProjectileBase>());
// 비동기 로드 코루틴 추가
coroutines.Add(StartCoroutine(LoadProjectile(data, add1value, addslidevalue)));
}
// 🔹 모든 코루틴이 끝날 때까지 대기
foreach (var c in coroutines)
yield return c;
// 🔹 한 배치 끝날 때마다 살짝 쉬기 (선택 사항)
yield return null;
}
LoadComplete = true;
}
private IEnumerator LoadProjectile(ProjectileTableData data, float add1value, Action<float> addslidevalue)
{
bool done = false;
yield return AddrResourceMgr.Ins.LoadObjectSequential<GameObject>(
$"Ingame/Projectile/{data.s_Projectile}.prefab",
prefab =>
{
for (int k = 0; k < data.n_LoadAmount; k++)
{
var proj = DSUtil.Get_Clone<ProjectileBase>(prefab, transform, Vector3.right * 10000f);
#if UNITY_EDITOR
if (proj == null)
MyEditorDialog.Show_Dialog($"{data.s_Projectile} 투사체에 ProjectileBase 스크립트가 없습니다.", null);
#endif
proj.Off_AfterOneShot(data);
dic_projectile[data.s_Projectile].Add(proj);
}
addslidevalue?.Invoke(add1value);
done = true;
});
// 완료될 때까지 대기 (혹시 비동기일 경우 대비)
yield return new WaitUntil(() => done);
}
ProjectileBase Get_Projectile(string projetile)
{
if (dic_projectile.ContainsKey(projetile))
{
for (int i = 0; i < dic_projectile[projetile].Count; i++)
{
if (!dic_projectile[projetile][i].isActiveAndEnabled)
return dic_projectile[projetile][i];
}
var newproj = DSUtil.Get_Clone<ProjectileBase>(dic_projectile[projetile][0].gameObject, transform);
newproj.gameObject.SetActive(false);
newproj.Off_AfterOneShot(dic_projectile[projetile][0].Get_Data());
dic_projectile[projetile].Add(newproj);
return newproj;
}
else
Popup.Ins.Set($"{projetile} 투사체가 없습니다. 테이블을 확인해 주세요.");
return null;
}
public void Shoot_Projectile(ProjectileData pdata, Vector3 start, Vector3 end, Actor target, Action<Actor> act_end)
{
var crirate = pdata.Hitter != null ? pdata.Hitter.Get_ActorStatInfo().Get_TotalStat(eStat.Cri) : 0;
pdata.isCri = DSUtil.RandomTrue(crirate);
var proj = Get_Projectile(pdata.s_Projectile);
proj.Set(pdata, start, end, target, act_end);
}
public void Set_Scale(string proj, float scale)
{
for (int i = 0; i < dic_projectile[proj].Count; i++)
dic_projectile[proj][i].Set_Scale(scale);
}
}