Main/Component/UI/Effect/ActorEffectEvent.cs
File was deleted Main/Component/UI/Effect/ActorEffectEvent.cs.meta
File was deleted Main/Component/UI/Effect/EffectPlayer.cs
@@ -4,16 +4,17 @@ 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; @@ -21,9 +22,63 @@ 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() @@ -33,20 +88,29 @@ 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; @@ -58,67 +122,42 @@ 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() { @@ -130,7 +169,7 @@ } // 创建后的特效会自动隐藏 需要手动调用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; @@ -144,10 +183,8 @@ { effectPlayer = parent.AddMissingComponent<EffectPlayer>(); effectPlayer.effectId = effectId; effectPlayer.autoDestroy = _autoDestroy; effectPlayer.destroyDelay = _destroyDelay; } effectPlayer.SetActive(false); effectPlayer.SetActive(true); return effectPlayer; } @@ -156,22 +193,21 @@ 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(); } @@ -181,23 +217,19 @@ { 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(); } @@ -208,18 +240,13 @@ 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); @@ -231,8 +258,7 @@ } // 粒子特效 var particles = effectTarget.GetComponentsInChildren<ParticleSystem>(true); foreach (var ps in particles) foreach (var ps in particleList) { if (ps.IsAlive()) { @@ -242,4 +268,20 @@ 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; } } } Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@ //-------------------------------------------------------- // [Author]: YYL // [ Date ]: Friday, June 27, 2025 // [ Date ]: 2025年7月22日 //-------------------------------------------------------- using System.Collections.Generic; @@ -15,13 +15,13 @@ public int id; public string packageName; public int isSpine; public string fxName; public int job; public int audio; public int stopImmediate; public int setParent; public string nodeName; public int notShow; public int autoDestroy; public float destroyDelay; public override int LoadKey(string _key) { @@ -37,19 +37,19 @@ packageName = tables[1]; fxName = tables[2]; int.TryParse(tables[2],out isSpine); int.TryParse(tables[3],out job); fxName = tables[3]; int.TryParse(tables[4],out audio); int.TryParse(tables[5],out stopImmediate); nodeName = tables[5]; int.TryParse(tables[6],out setParent); int.TryParse(tables[6],out notShow); nodeName = tables[7]; int.TryParse(tables[7],out autoDestroy); int.TryParse(tables[8],out notShow); float.TryParse(tables[8],out destroyDelay); } catch (Exception exception) { Main/Core/SFX/SFXController.cs
File was deleted Main/Core/SFX/SFXController.cs.meta
File was deleted Main/Core/SFX/SFXPlayUtility.cs
File was deleted Main/Core/SFX/SFXPlayUtility.cs.meta
File was deleted Main/System/Battle/BattleEffectMgr.cs
@@ -48,12 +48,11 @@ effectDict[effectId] = new List<EffectPlayer>(); } EffectPlayer effectPlayer = EffectPlayer.Create(effectId, parent, true, false); EffectPlayer effectPlayer = EffectPlayer.Create(effectId, parent); effectPlayer.onDestroy = OnEffectDestroy; if (effectPlayer != null) { effectDict[effectId].Add(effectPlayer); effectPlayer.Play(); } return effectPlayer; } Main/System/Battle/BattleField/BattleField.cs
@@ -290,4 +290,17 @@ // return round > xxx; return false; } public void UpdateCanvas(Canvas canvas) { EffectPenetrationBlocker[] blockers = battleRootNode.GetComponentsInChildren<EffectPenetrationBlocker>(true); if (null != blockers) { foreach (var blocker in blockers) { blocker.SetParentCanvas(canvas); } } } } Main/System/Battle/BattleWin.cs
@@ -35,10 +35,7 @@ protected override void OnPreOpen() { base.OnPreOpen(); SetBattleField(BattleManager.Instance.storyBattleField); // SetBattleField(BattleManager.Instance.storyBattleField); } protected override void OnPreClose() @@ -96,5 +93,6 @@ } ui.SetBattleField(battleField); battleField.UpdateCanvas(canvas); } } Main/System/Battle/SkillEffect/BulletSkillEffect.cs
@@ -76,7 +76,6 @@ { EffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.EffectId, caster.effectNode); effectPlayer.Play(); RectTransform effectTrans = effectPlayer.transform as RectTransform; @@ -88,7 +87,7 @@ // 击中就销毁子弹 caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.EffectId, effectPlayer); // 播放子弹爆炸特效 caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplotionEffectId, target).Play(); caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplotionEffectId, target); }); caster.battleField.battleTweenMgr.OnPlayTween(tween); Main/System/Battle/SkillEffect/NormalSkillEffect.cs
@@ -21,14 +21,15 @@ public override void Play(Action<int, List<H0604_tagUseSkillAttack.tagSkillHurtObj>> _onHit) { Action<int, List<H0604_tagUseSkillAttack.tagSkillHurtObj>> onHitFormation = (_hitIndex, _hurtList) => // 特效炸开在阵容的中间的回调 Action<int, List<H0604_tagUseSkillAttack.tagSkillHurtObj>> onHitLineUpCenter = (_hitIndex, _hurtList) => { _onHit?.Invoke(_hitIndex, tagUseSkillAttack.HurtList.ToList()); }; if (skillConfig.effectAnchor == SkillEffectAnchor.Caster) { CastInTarget(caster.heroGo.transform as RectTransform, onHitFormation); CastInTarget(caster.heroGo.transform as RectTransform, onHitLineUpCenter); } else if (skillConfig.effectAnchor == SkillEffectAnchor.Target) { @@ -53,11 +54,11 @@ } else if (skillConfig.effectAnchor == SkillEffectAnchor.AlliesCenter) { CastInTarget(caster.battleField.GetTeamNode(caster.Camp), onHitFormation); CastInTarget(caster.battleField.GetTeamNode(caster.Camp), onHitLineUpCenter); } else if (skillConfig.effectAnchor == SkillEffectAnchor.EnemiesCenter) { CastInTarget(caster.battleField.GetTeamNode(caster.Camp == BattleCamp.Blue ? BattleCamp.Red : BattleCamp.Blue), onHitFormation); CastInTarget(caster.battleField.GetTeamNode(caster.Camp == BattleCamp.Blue ? BattleCamp.Red : BattleCamp.Blue), onHitLineUpCenter); } else { @@ -69,8 +70,6 @@ { EffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.EffectId, caster.effectNode); effectPlayer.Play(); RectTransform effectTrans = effectPlayer.transform as RectTransform; _onHit?.Invoke(0, null); @@ -78,7 +77,7 @@ // 销毁自身上的特效应该是等特效播放完毕之后 // caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.EffectId, effectPlayer); // 播放受击特效 caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplotionEffectId, target).Play(); caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.ExplotionEffectId, target); } Main/System/UIBase/UIBase.cs
@@ -358,19 +358,12 @@ /// <param name="autoDestroy">是否自动销毁,默认为true</param> /// <param name="destroyDelay">自动销毁延迟时间,默认为5秒</param> /// <returns>特效游戏对象</returns> public EffectPlayer PlayUIEffect(int id, Transform parent = null, bool autoDestroy = true, float destroyDelay = 5f) public EffectPlayer PlayUIEffect(int id, Transform parent = null) { // 使用默认值 if (parent == null) parent = transform; EffectPlayer player = parent.gameObject.AddComponent<EffectPlayer>(); player.effectId = id; player.autoDestroy = autoDestroy; player.destroyDelay = destroyDelay; player.canvas = canvas; return player; return EffectPlayer.Create(id, parent, false); } #endregion Main/Utility/EffectPenetrationBlocker.cs
@@ -133,7 +133,30 @@ parentCanvas = canvas; if (autoAdjustSorting) { UpdateSortingOrder(); this.DelayFrame(UpdateSortingOrder); } } /// <summary> /// 应用遮罩区域(RectTransform),可用于裁剪特效 /// </summary> public void PerformMask(RectTransform maskRect) { // 这里只是示例,实际可根据你的Shader或特效材质做裁剪 foreach (Renderer renderer in effectRenderers) { if (renderer != null && renderer.material != null && maskRect != null) { Vector3[] corners = new Vector3[4]; maskRect.GetWorldCorners(corners); Vector4 clipRect = new Vector4(corners[0].x, corners[0].y, corners[2].x, corners[2].y); renderer.material.SetVector("_ClipRect", clipRect); renderer.material.SetFloat("_UseClipRect", 1); } else if (renderer != null && renderer.material != null) { renderer.material.SetFloat("_UseClipRect", 0); } } }