using System; using System.Collections; using System.Collections.Generic; using Spine.Unity; using UnityEngine; using Spine; using UnityEngine.UI; public class EffectPlayer : MonoBehaviour { public int effectId; public EffectConfig effectConfig; public Action onDestroy; public float speedRate = 1f; [HideInInspector] public Canvas canvas = null; [HideInInspector] public GameObject effectTarget = null; protected EffectPenetrationBlocker blocker = null; protected bool isInit = false; protected List particleList = new List(); protected List animatorList = new List(); protected List rendererList = new List(); protected SkeletonGraphic spineComp; protected void Start() { ReStart(); } protected void InitCompnent() { if (effectId <= 0) { effectConfig = null; Debug.LogError("EffectPlayer effectId is not set"); #if UNITY_EDITOR UnityEditor.Selection.activeGameObject = gameObject; UnityEditor.EditorGUIUtility.PingObject(gameObject); #endif return; } effectConfig = EffectConfig.Get(effectId); if (null == effectConfig) { Debug.LogError("could not find effect config, effect id is " + effectId); #if UNITY_EDITOR UnityEditor.Selection.activeGameObject = gameObject; UnityEditor.EditorGUIUtility.PingObject(gameObject); #endif return; } particleList.Clear(); animatorList.Clear(); rendererList.Clear(); spineComp = null; if (effectConfig.isSpine != 0) { spineComp = gameObject.GetComponentInChildren(true); } else { // 收集组件 particleList.AddRange(gameObject.GetComponentsInChildren(true)); animatorList.AddRange(gameObject.GetComponentsInChildren(true)); } rendererList.AddRange(gameObject.GetComponentsInChildren(true)); } public void Stop() { if (null != effectTarget) { DestroyImmediate(effectTarget); effectTarget = null; } isInit = false; particleList.Clear(); animatorList.Clear(); rendererList.Clear(); spineComp = null; } public void Play() { ReStart(); } protected void ReStart() { if (!isInit) { isInit = true; InitCompnent(); } if (EffectMgr.Instance.IsNotShowBySetting(effectId)) { return; } if (null != effectTarget) { DestroyImmediate(effectTarget); effectTarget = null; } // YYL TODO // 在这里考虑用池的话可能走配置好一点 原本的是无论如何都走池 但是实际上有些特效并不需要 // 加载特效资源 var effectPrefab = ResManager.Instance.LoadAsset("UIEffect/" + effectConfig.packageName, effectConfig.fxName); if (effectPrefab == null) { Debug.LogError($"加载UI特效失败: {effectConfig.packageName}"); return; } // 实例化特效 effectTarget = Instantiate(effectPrefab, transform); effectTarget.name = $"Effect_{effectConfig.fxName}"; // 思考一下在没有挂在节点的时候 if (null == canvas) canvas = GetComponentInParent(); // 添加特效穿透阻挡器 blocker = effectTarget.AddMissingComponent(); // 如果没有canvas的话 正常是因为不在BattleWin下面的节点 意思就是当前没有显示 等到切回战斗的时候再通过BattleField.UpdateCanvas来更新 if (canvas != null) { blocker.SetParentCanvas(canvas); } // 自动销毁 if (effectConfig.autoDestroy != 0) { Destroy(effectTarget, effectConfig.destroyDelay); } } protected void OnDestroy() { if (onDestroy != null) { onDestroy.Invoke(this); onDestroy = null; } } // 创建后的特效会自动隐藏 需要手动调用Play才能播放 public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false) { EffectPlayer effectPlayer = null; if (createNewChild) { GameObject newGo = new GameObject("EffectPlayer_" + effectId); newGo.transform.SetParent(parent, false); effectPlayer = newGo.AddComponent(); } else { effectPlayer = parent.AddMissingComponent(); effectPlayer.effectId = effectId; } effectPlayer.SetActive(true); return effectPlayer; } public void Pause() { if (effectTarget == null) return; // Spine动画 // var spineGraphics = effectTarget.GetComponentsInChildren(true); // foreach (var sg in spineGraphics) if (spineComp != null) { spineComp.timeScale = 0f; } // Animator动画 foreach (var animator in animatorList) { animator.speed = 0f; } // 粒子特效 foreach (var ps in particleList) { ps.Pause(); } } public void Resume() { if (effectTarget == null) return; if (spineComp != null) { spineComp.timeScale = speedRate; } // Animator动画 foreach (var animator in animatorList) { animator.speed = speedRate; } // 粒子特效 foreach (var ps in particleList) { ps.Play(); } } public bool IsFinish() { if (effectTarget == null) return true; // Spine动画 if (!spineComp.AnimationState.GetCurrent(0).IsComplete) { return false; } // Animator动画 foreach (var animator in animatorList) { AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); // 循环动画不考虑结束的问题 if (!stateInfo.loop && stateInfo.normalizedTime < 1f) { return false; } } // 粒子特效 foreach (var ps in particleList) { if (ps.IsAlive()) { return false; } } return true; } /// /// 设置遮罩(支持RectMask2D、Mask、SmoothMask等) /// public void SetMask(RectTransform maskArea = null) { if (effectTarget == null || blocker == null) return; // 优先使用传入的maskArea if (maskArea != null) { blocker.PerformMask(maskArea); return; } } }