| | |
| | | using Spine.Unity; |
| | | using UnityEngine; |
| | | using Spine; |
| | | using UnityEngine.UI; |
| | | |
| | | public class EffectPlayer : MonoBehaviour |
| | | { |
| | | public int effectId; |
| | | |
| | | public bool autoDestroy = false; |
| | | |
| | | public float destroyDelay = 0f; |
| | | public EffectConfig effectConfig; |
| | | |
| | | public Action<EffectPlayer> onDestroy; |
| | | |
| | | public float speedRate = 1f; |
| | | |
| | | [HideInInspector] public Canvas canvas = null; |
| | | |
| | |
| | | |
| | | protected EffectPenetrationBlocker blocker = null; |
| | | |
| | | protected bool isInit = false; |
| | | |
| | | protected List<ParticleSystem> particleList = new List<ParticleSystem>(); |
| | | |
| | | protected List<Animator> animatorList = new List<Animator>(); |
| | | |
| | | protected List<Renderer> rendererList = new List<Renderer>(); |
| | | |
| | | 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<SkeletonGraphic>(true); |
| | | } |
| | | else |
| | | { |
| | | // 收集组件 |
| | | particleList.AddRange(gameObject.GetComponentsInChildren<ParticleSystem>(true)); |
| | | animatorList.AddRange(gameObject.GetComponentsInChildren<Animator>(true)); |
| | | } |
| | | rendererList.AddRange(gameObject.GetComponentsInChildren<Renderer>(true)); |
| | | } |
| | | |
| | | public void Stop() |
| | |
| | | DestroyImmediate(effectTarget); |
| | | effectTarget = null; |
| | | } |
| | | |
| | | isInit = false; |
| | | |
| | | particleList.Clear(); |
| | | animatorList.Clear(); |
| | | rendererList.Clear(); |
| | | spineComp = null; |
| | | } |
| | | |
| | | public void Play() |
| | | { |
| | | if (!isActiveAndEnabled) |
| | | { |
| | | gameObject.SetActive(true); |
| | | } |
| | | ReStart(); |
| | | } |
| | | |
| | | |
| | | protected void ReStart() |
| | | { |
| | | if (!isInit) |
| | | { |
| | | isInit = true; |
| | | InitCompnent(); |
| | | } |
| | | |
| | | if (EffectMgr.Instance.IsNotShowBySetting(effectId)) |
| | | { |
| | | return; |
| | |
| | | effectTarget = null; |
| | | } |
| | | |
| | | EffectConfig effectCfg = EffectConfig.Get(effectId); |
| | | |
| | | if (null == effectCfg) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | // YYL TODO |
| | | // 在这里考虑用池的话可能走配置好一点 原本的是无论如何都走池 但是实际上有些特效并不需要 |
| | | |
| | | // 加载特效资源 |
| | | var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectCfg.packageName, effectCfg.fxName); |
| | | var effectPrefab = ResManager.Instance.LoadAsset<GameObject>("UIEffect/" + effectConfig.packageName, effectConfig.fxName); |
| | | if (effectPrefab == null) |
| | | { |
| | | Debug.LogError($"加载UI特效失败: {effectCfg.packageName}"); |
| | | Debug.LogError($"加载UI特效失败: {effectConfig.packageName}"); |
| | | return; |
| | | } |
| | | |
| | | // 实例化特效 |
| | | effectTarget = Instantiate(effectPrefab, transform); |
| | | effectTarget.name = $"Effect_{effectCfg.fxName}"; |
| | | effectTarget.name = $"Effect_{effectConfig.fxName}"; |
| | | |
| | | // 思考一下在没有挂在节点的时候 |
| | | if (null == canvas) |
| | | canvas = GetComponentInParent<Canvas>(); |
| | | |
| | | if (null == canvas) |
| | | { |
| | | Debug.LogError("can not find canvas for UIEffect " + effectId); |
| | | return; |
| | | } |
| | | |
| | | // 添加特效穿透阻挡器 |
| | | blocker = effectTarget.AddMissingComponent<EffectPenetrationBlocker>(); |
| | | blocker.parentCanvas = canvas; |
| | | |
| | | // 延迟一帧才生效 |
| | | this.DelayFrame(blocker.UpdateSortingOrder); |
| | | |
| | | // blocker.UpdateSortingOrder(); |
| | | // 如果没有canvas的话 正常是因为不在BattleWin下面的节点 意思就是当前没有显示 等到切回战斗的时候再通过BattleField.UpdateCanvas来更新 |
| | | if (canvas != null) |
| | | { |
| | | blocker.SetParentCanvas(canvas); |
| | | } |
| | | |
| | | // 自动销毁 |
| | | if (autoDestroy) |
| | | if (effectConfig.autoDestroy != 0) |
| | | { |
| | | Destroy(effectTarget, destroyDelay); |
| | | Destroy(effectTarget, effectConfig.destroyDelay); |
| | | } |
| | | } |
| | | |
| | | public void SetSortingOrderOffset(int offset) |
| | | { |
| | | // 被Destroy之后effectTarget == null 为 true 但是访问内容会报错 |
| | | if (blocker != null && effectTarget != null) |
| | | { |
| | | blocker.sortingOrderOffset = offset; |
| | | blocker.UpdateSortingOrder(); |
| | | } |
| | | else |
| | | { |
| | | blocker = null; |
| | | effectTarget = null; |
| | | } |
| | | } |
| | | |
| | | protected void OnDestroy() |
| | | { |
| | |
| | | } |
| | | |
| | | // 创建后的特效会自动隐藏 需要手动调用Play才能播放 |
| | | public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false, bool _autoDestroy = true, float _destroyDelay = 5f) |
| | | public static EffectPlayer Create(int effectId, Transform parent, bool createNewChild = false) |
| | | { |
| | | EffectPlayer effectPlayer = null; |
| | | |
| | |
| | | { |
| | | effectPlayer = parent.AddMissingComponent<EffectPlayer>(); |
| | | effectPlayer.effectId = effectId; |
| | | effectPlayer.autoDestroy = _autoDestroy; |
| | | effectPlayer.destroyDelay = _destroyDelay; |
| | | } |
| | | effectPlayer.SetActive(false); |
| | | effectPlayer.SetActive(true); |
| | | return effectPlayer; |
| | | } |
| | | |
| | |
| | | if (effectTarget == null) return; |
| | | |
| | | // Spine动画 |
| | | var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true); |
| | | foreach (var sg in spineGraphics) |
| | | // var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true); |
| | | // foreach (var sg in spineGraphics) |
| | | if (spineComp != null) |
| | | { |
| | | sg.timeScale = 0f; |
| | | spineComp.timeScale = 0f; |
| | | } |
| | | |
| | | // Animator动画 |
| | | var animators = effectTarget.GetComponentsInChildren<Animator>(true); |
| | | foreach (var animator in animators) |
| | | foreach (var animator in animatorList) |
| | | { |
| | | animator.speed = 0f; |
| | | } |
| | | |
| | | // 粒子特效 |
| | | var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true); |
| | | foreach (var ps in particles) |
| | | foreach (var ps in particleList) |
| | | { |
| | | ps.Pause(); |
| | | } |
| | |
| | | { |
| | | if (effectTarget == null) return; |
| | | |
| | | // Spine动画 |
| | | var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true); |
| | | foreach (var sg in spineGraphics) |
| | | if (spineComp != null) |
| | | { |
| | | sg.timeScale = 1f; |
| | | spineComp.timeScale = speedRate; |
| | | } |
| | | |
| | | // Animator动画 |
| | | var animators = effectTarget.GetComponentsInChildren<Animator>(true); |
| | | foreach (var animator in animators) |
| | | foreach (var animator in animatorList) |
| | | { |
| | | animator.speed = 1f; |
| | | animator.speed = speedRate; |
| | | } |
| | | |
| | | // 粒子特效 |
| | | var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true); |
| | | foreach (var ps in particles) |
| | | foreach (var ps in particleList) |
| | | { |
| | | ps.Play(); |
| | | } |
| | |
| | | if (effectTarget == null) return true; |
| | | |
| | | // Spine动画 |
| | | var spineGraphics = effectTarget.GetComponentsInChildren<SkeletonGraphic>(true); |
| | | foreach (var sg in spineGraphics) |
| | | if (!spineComp.AnimationState.GetCurrent(0).IsComplete) |
| | | { |
| | | if (!sg.AnimationState.GetCurrent(0).IsComplete) |
| | | { |
| | | return false; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // Animator动画 |
| | | var animators = effectTarget.GetComponentsInChildren<Animator>(true); |
| | | foreach (var animator in animators) |
| | | foreach (var animator in animatorList) |
| | | { |
| | | AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); |
| | | |
| | |
| | | } |
| | | |
| | | // 粒子特效 |
| | | var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true); |
| | | foreach (var ps in particles) |
| | | foreach (var ps in particleList) |
| | | { |
| | | if (ps.IsAlive()) |
| | | { |
| | |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 设置遮罩(支持RectMask2D、Mask、SmoothMask等) |
| | | /// </summary> |
| | | public void SetMask(RectTransform maskArea = null) |
| | | { |
| | | if (effectTarget == null || blocker == null) |
| | | return; |
| | | |
| | | // 优先使用传入的maskArea |
| | | if (maskArea != null) |
| | | { |
| | | blocker.PerformMask(maskArea); |
| | | return; |
| | | } |
| | | } |
| | | } |