yyl
2 天以前 a178792731891bcd477ab0812ced1ab5fb9229fc
125 战斗 闪避增加幻影
2个文件已修改
2个文件已添加
208 ■■■■ 已修改文件
Main/Component/UI/Common/SkeletonIllusionShadow.cs 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/SkeletonIllusionShadow.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObject.cs 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Motion/MotionBase.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/SkeletonIllusionShadow.cs
New file
@@ -0,0 +1,128 @@
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using Spine;
using Spine.Unity;
using UnityEngine;
public class SkeletonIllusionShadow : MonoBehaviour
{
    // 记录所有残影对象,便于统一销毁
    private readonly List<GameObject> illusionShadows = new List<GameObject>();
    private SkeletonAnimation skeletonAnimation;
    private bool createSwitch = false;
    private int curFrame = 0;
    private int frameInteral = 2;
    public void SetSkeletonAnimation(SkeletonAnimation _skeletonAnimation)
    {
        skeletonAnimation = _skeletonAnimation;
    }
    public void Show(bool v)
    {
        createSwitch = v;
        curFrame = 0;
        if (!v)
        {
            // 清理所有残影对象
            for (int i = illusionShadows.Count - 1; i >= 0; i--)
            {
                var go = illusionShadows[i];
                if (go != null)
                {
                    DOTween.Kill(go, complete: false);
                    if (Application.isPlaying)
                        Destroy(go);
                    else
                        DestroyImmediate(go);
                }
            }
            illusionShadows.Clear();
        }
    }
    public void Run()
    {
        if (createSwitch)
        {
            //  0.1秒创建一个残像
            curFrame++;
            if (curFrame >= frameInteral)
            {
                curFrame -= frameInteral;
                CreateIllusionShadow();
            }
        }
    }
    private void CreateIllusionShadow()
    {
        var src = skeletonAnimation.transform;
        // 保存源的世界变换
        Vector3 worldPos = src.position;
        Quaternion worldRot = src.rotation;
        Vector3 worldScale = src.lossyScale;
        GameObject objTest = new GameObject("IllusionShadow");
        illusionShadows.Add(objTest);
        objTest.transform.SetParent(null, false);
        objTest.transform.position = worldPos;
        objTest.transform.rotation = worldRot;
        objTest.transform.localScale = worldScale; // 当 parent == null 时 localScale == worldScale
        objTest.layer = LayerMask.NameToLayer("UI");
        SkeletonAnimation sa = SkeletonAnimation.AddToGameObject(objTest, skeletonAnimation.skeletonDataAsset, false);
        TrackEntry trackEntry = skeletonAnimation.AnimationState.GetCurrent(0);
        TrackEntry playedEntry = sa.AnimationState.SetAnimation(0, trackEntry.Animation.Name, trackEntry.Loop);
        playedEntry.TrackTime = trackEntry.TrackTime;
        sa.timeScale = 0;
        sa.AnimationState.TimeScale = 0;
        playedEntry.TimeScale = 0;
        RendererAdjuster parent = skeletonAnimation.GetComponentInParent<RendererAdjuster>();
        objTest.AddMissingComponent<RendererAdjuster>().SetSortingOrder(parent.sortingOrder);
        sa.skeleton.A = skeletonAnimation.skeleton.A;
        // 使用DoTween做alpha淡出,Tween与objTest绑定,便于统一Kill
        DOTween.To(() => sa.skeleton.A, x => { sa.skeleton.A = x; sa.LateUpdate(); }, 0f, 0.5f)
            .SetTarget(objTest);
        // 安全销毁,移除引用
        _ = DestroyIllusionShadowAfterAsync(objTest, 0.5f);
    }
    // 用UniTask安全延迟销毁残影对象,多重安全检查
    private async UniTaskVoid DestroyIllusionShadowAfterAsync(GameObject go, float delay)
    {
        try
        {
            await UniTask.Delay((int)(delay * 1000), cancellationToken: this.GetCancellationTokenOnDestroy());
        }
        catch (OperationCanceledException)
        {
            // 对象已销毁,无需处理
            return;
        }
        if (go == null) return;
        DOTween.Kill(go, complete: false);
        illusionShadows.Remove(go);
        if (Application.isPlaying)
            Destroy(go);
        else
            DestroyImmediate(go);
    }
}
Main/Component/UI/Common/SkeletonIllusionShadow.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97920429032421a4081acb2dee82e387
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleObject/BattleObject.cs
@@ -288,13 +288,21 @@
        teamHero.curHp = Math.Max(0, teamHero.curHp - (int)bounceHP);
    }
    const float pingpongTime = 0.2f;
    //  闪避开始
    public virtual void OnDodgeBegin()
    {
        float pingpongTime = 0.2f;
        RectTransform rectTrans = heroRectTrans;
        var tween = rectTrans.DOAnchorPos(new Vector3(-30, 0, 0), pingpongTime)
            .SetEase(Ease.OutCubic);
        motionBase.ShowIllusionShadow(true);
        tween.onComplete += () =>
        {
            motionBase.ShowIllusionShadow(false);
        };
        battleField.battleTweenMgr.OnPlayTween(tween);
    }
@@ -302,7 +310,6 @@
    //  闪避结束
    public virtual void OnDodgeEnd(Action _complete = null)
    {
        float pingpongTime = 0.2f;
        RectTransform rectTrans = heroRectTrans;
        var tween = rectTrans.DOAnchorPos(Vector3.zero, pingpongTime)
Main/System/Battle/Motion/MotionBase.cs
@@ -43,6 +43,9 @@
    #endregion
    private Spine.TrackEntry currentTrackEntry;
    //  残影生成器
    private SkeletonIllusionShadow illusionShadow;
    
    #region 初始化方法
@@ -79,8 +82,8 @@
        {
            BattleDebug.LogError("缺少SkeletonGraphic组件!");
        }
        illusionShadow = _skeletonAnimation.gameObject.AddMissingComponent<SkeletonIllusionShadow>();
    }
    
    public virtual void Release()
@@ -377,33 +380,34 @@
    public virtual void Run()
    {
// #if UNITY_EDITOR
//         List<int> removeIndex = new List<int>();
// #endif
        // #if UNITY_EDITOR
        //         List<int> removeIndex = new List<int>();
        // #endif
        for (int i = runActionList.Count - 1; i >= 0; i--)
        {
// #if UNITY_EDITOR
//             try
//             {
// #endif
                runActionList[i]?.Invoke();
// #if UNITY_EDITOR
//             }
//             catch (System.Exception ex)
//             {
//                 removeIndex.Add(i);
//                 BattleDebug.LogError($"执行RunAction时发生异常: {ex.Message}\n{ex.StackTrace}");
//             }
// #endif
            // #if UNITY_EDITOR
            //             try
            //             {
            // #endif
            runActionList[i]?.Invoke();
            // #if UNITY_EDITOR
            //             }
            //             catch (System.Exception ex)
            //             {
            //                 removeIndex.Add(i);
            //                 BattleDebug.LogError($"执行RunAction时发生异常: {ex.Message}\n{ex.StackTrace}");
            //             }
            // #endif
        }
// #if UNITY_EDITOR
//         // 移除失败的Action
//         for (int i = 0; i < removeIndex.Count; i++)
//         {
//             runActionList.RemoveAt(removeIndex[i]);
//         }
// #endif
        // #if UNITY_EDITOR
        //         // 移除失败的Action
        //         for (int i = 0; i < removeIndex.Count; i++)
        //         {
        //             runActionList.RemoveAt(removeIndex[i]);
        //         }
        // #endif
        illusionShadow.Run();
    }
    public virtual void Pause()
@@ -432,6 +436,12 @@
        skeletonAnimation.timeScale = ratio;
    }
    public void ShowIllusionShadow(bool v)
    {
        illusionShadow.SetSkeletonAnimation(skeletonAnimation);
        illusionShadow.Show(v);
    }
    #endregion
}