using System; using System.Collections; using UnityEngine; public class ProjectileBase : MonoBehaviour { ProjectileTableData m_TableData; Vector3 offset = new Vector3(0f, 0f); float m_Speed; private void Awake() { //GetComponent().sortingOrder = 10; var particles = GetComponentsInChildren(); for (int i = 0; i < particles.Length; i++) { var main = particles[i].main; main.scalingMode = ParticleSystemScalingMode.Hierarchy; var rend = particles[i].GetComponent(); if (rend != null) rend.sortingOrder += 10; // 기존 값에서 +10 } } public void Set(ProjectileData pdata, Vector3 start, Vector3 end, Actor target, Action act_end) { gameObject.SetActive(true); m_Speed = pdata.m_Speed; if (m_Speed <= 0f) m_Speed = 15f; // 이펙트 툴용 transform.eulerAngles = Vector3.zero; offset = new Vector3(m_TableData.f_PositionX, m_TableData.f_PositionY); end += offset; if (m_TableData.b_FilpX && transform.localScale.x > 0f) transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z); if (pdata.e_AttackType == eAttackType.Melee) { // 즉시 공격 StartCoroutine(Co_Melee(end, target, act_end)); } else { // 투사체 이동 StartCoroutine(Co_Update(start, end, target, act_end)); } } IEnumerator Co_Melee(Vector3 end, Actor target, Action act_end) { transform.position = end; if (m_TableData != null && !string.IsNullOrEmpty(m_TableData.s_Effect)) { var delay = table_effect.Ins.Get_Data(m_TableData.s_Effect).f_EffectDelay; yield return new WaitForSeconds(delay); EffectMgr.Ins.Show_Effect(m_TableData.s_Effect, transform.position); } act_end?.Invoke(target); yield return new WaitForSeconds(1f); gameObject.SetActive(false); } IEnumerator Co_Update(Vector3 start, Vector3 end, Actor target, Action act_end) { bool isTarget = target; transform.position = start; var ps = GetComponent(); if (ps) { // Trail 완전 비활성화 var trails = ps.trails; bool wasTrailOn = trails.enabled; trails.enabled = false; // 파티클 완전 정지 및 초기화 ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); ps.Clear(true); foreach (var tr in GetComponentsInChildren()) tr.Clear(); // 1프레임 대기 (렌더 버퍼 플러시) yield return null; // 파티클 리셋 + Trail 다시 켜기 ps.Simulate(0f, true, true, true); if (wasTrailOn) trails.enabled = true; ps.Play(true); } while (Vector3.Distance(transform.position, end) > 0.01f) { if (isTarget) { if (target.IsRole(eRole.Mob) && target.IsDead()) { var mobindex = target.Get_MobIndex(); if (mobindex < 0) mobindex += 3; // 라인 교체로 내려갔을 수도 있으므로 기존 위치로 잡음 var nexttarget = InGameInfo.Ins.Get_Enemy_orNull(eRole.PC, mobindex + 3); var nexttarget2 = InGameInfo.Ins.Get_Enemy_orNull(eRole.PC, mobindex + 6); if (nexttarget && !nexttarget.IsDead()) target = nexttarget; else if (nexttarget2 && !nexttarget2.IsDead()) target = nexttarget2; } end = target.Get_World_Position() + offset; } transform.LookAt(end); transform.position = Vector3.MoveTowards( transform.position, end, m_Speed * Time.deltaTime ); yield return null; } if (m_TableData != null && !string.IsNullOrEmpty(m_TableData.s_Effect)) { var delay = table_effect.Ins.Get_Data(m_TableData.s_Effect).f_EffectDelay; yield return new WaitForSeconds(delay); EffectMgr.Ins.Show_Effect(m_TableData.s_Effect, transform.position); } act_end?.Invoke(target); gameObject.SetActive(false); } public void Off_AfterOneShot(ProjectileTableData tdata) { m_TableData = tdata; Set_Scale(tdata.f_Scale); if (gameObject.activeInHierarchy) StartCoroutine(Co_Off()); } public ProjectileTableData Get_Data() { return m_TableData; } public void Set_Scale(float scale) { transform.localScale = Vector3.one * scale; } IEnumerator Co_Off() { yield return new WaitForSeconds(1f); gameObject.SetActive(false); } }