From ed98029a88cd89702980ac7c40b711afddc5aeb2 Mon Sep 17 00:00:00 2001
From: hch <305670599@qq.com>
Date: 星期四, 20 十一月 2025 14:44:59 +0800
Subject: [PATCH] Merge branch 'master' of http://mobile.secondworld.net.cn:10010/r/Project_SG_scripts
---
Main/System/Battle/Motion/MotionBase.cs | 730 ++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 530 insertions(+), 200 deletions(-)
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index 9c2fddb..9539668 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -1,247 +1,577 @@
using System;
-using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity;
-using Cysharp.Threading.Tasks;
-/// <summary>
-/// 瑙掕壊鍔ㄧ敾鍩虹被锛屽鐞嗘墍鏈変笌鍔ㄧ敾鐩稿叧鐨勫姛鑳�
-/// </summary>
public class MotionBase
{
- public class WaitingTask
+ public float MotionTimeScale = 1f;
+ public static List<string> AttackMotionList = new List<string>
{
- public List<int> triggerFrame;
- public MotionName motionName;
- public int currentFrame;
- public Action<MotionName, int> callback;
+ MotionName.attack.ToString().ToLower(),
+ MotionName.angerSkill.ToString().ToLower(),
+ MotionName.passiveSkill.ToString().ToLower(),
+ };
- public WaitingTask(List<int> triggerFrame, MotionName motionName, Action<MotionName, int> _callback)
+ private Dictionary<Spine.TrackEntry, Action> trackEntryCallbacks = new Dictionary<Spine.TrackEntry, Action>();
+ public Action OnAttackAnimationComplete;
+ public Action OnHitAnimationComplete;
+ private List<Action> runningActions = new List<Action>();
+
+ public SkeletonAnimation skeletonAnim;
+ protected Spine.AnimationState animState;
+ protected Spine.Skeleton skeleton;
+ protected float defaultMixDuration = 0f;
+ private Spine.TrackEntry currentTrack;
+ private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>();
+
+ // 瀛愭妧鑳借建閬撴睜绠$悊锛堝湪Init涓垵濮嬪寲锛屼笉瑕佸湪杩欓噷鍒濆鍖栵級
+ private Queue<int> availableSubTracks;
+ private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>();
+
+ private SkeletonIllusionShadow illusionShadow;
+ private bool playingSkillAnim = false;
+
+ private bool isUnderControl = false;
+
+ private float pauseTime = 0f;
+ private float resumeTime = 0f;
+
+ // 鏂板锛氱疮绉殏鍋滄椂闀匡紝鐢ㄤ簬瀵归潪鍔ㄧ敾璺緞(Time.time)杩涜绋冲畾鐨勬椂闂翠慨姝�
+ private float pausedAccumulated = 0f;
+ private float pauseStart = 0f;
+
+ public virtual void Init(SkeletonAnimation skelAnim)
+ {
+ skeletonAnim = skelAnim;
+ if (skeletonAnim == null)
{
- this.triggerFrame = triggerFrame;
- this.motionName = motionName;
- this.currentFrame = 0;
- this.callback = _callback;
+ BattleDebug.LogError("缂哄皯SkeletonGraphic缁勪欢!");
+ return;
}
- public bool IsFinished()
+ animState = skeletonAnim.AnimationState;
+ skeletonAnim.timeScale = MotionTimeScale;
+ skeleton = skeletonAnim.Skeleton;
+
+ if (animState != null)
+ animState.Data.DefaultMix = defaultMixDuration;
+
+ // 鍒濆鍖栧瓙鎶�鑳借建閬撴睜
+ availableSubTracks = new Queue<int>();
+ for (int i = 1; i <= 8; i++)
+ availableSubTracks.Enqueue(i);
+
+ PlayAnimation(MotionName.idle, true);
+ SetupAnimationHandlers();
+
+ if (skelAnim.gameObject != null)
+ illusionShadow = skelAnim.gameObject.AddMissingComponent<SkeletonIllusionShadow>();
+ }
+
+ public virtual void Release()
+ {
+ trackEntryCallbacks.Clear();
+ activeSkillTracks.Clear();
+ availableSubTracks?.Clear();
+ subSkillTrackMap.Clear();
+ if (animState != null)
{
- return triggerFrame.Count <= 0;
+ animState.Complete -= OnAnimationComplete;
+ animState.ClearTracks();
+ animState = null;
+ }
+ skeletonAnim = null;
+ skeleton = null;
+ currentTrack = null;
+ playingSkillAnim = false;
+ }
+
+ public virtual Spine.TrackEntry PlayAnimation(MotionName motionName, bool loop, Action onComplete = null)
+ {
+ if (playingSkillAnim || animState == null) return null;
+
+ if (currentTrack != null && !currentTrack.IsComplete && trackEntryCallbacks.TryGetValue(currentTrack, out var prevCallback))
+ {
+ trackEntryCallbacks.Remove(currentTrack);
+ prevCallback?.Invoke();
+ currentTrack = null;
}
- public void Run()
+ currentTrack = animState.SetAnimation(0, motionName.ToString(), loop);
+ if (onComplete != null && currentTrack != null)
+ trackEntryCallbacks[currentTrack] = onComplete;
+
+ return currentTrack;
+ }
+
+ public virtual Spine.TrackEntry PlayDeadAnimation(Action onComplete = null)
+ {
+ if (animState == null) return null;
+
+ // 浣跨敤杞ㄩ亾9浣滀负姝讳骸鍔ㄧ敾涓撶敤杞ㄩ亾锛堢嫭绔嬩簬涓昏建閬�0鍜屽瓙鎶�鑳借建閬�1-8锛�
+ const int deathTrackIndex = 9;
+
+ // 娓呴櫎姝讳骸杞ㄩ亾涓婄殑鍥炶皟
+ if (activeSkillTracks.TryGetValue(deathTrackIndex, out var oldDeathTrack))
{
- if (triggerFrame.Count > 0)
+ if (trackEntryCallbacks.ContainsKey(oldDeathTrack))
+ trackEntryCallbacks.Remove(oldDeathTrack);
+ }
+
+ Spine.Animation deadAnim = FindAnim(MotionName.dead.ToString());
+ if (deadAnim == null)
+ {
+ Debug.LogError("鎵句笉鍒版浜″姩鐢�");
+ onComplete?.Invoke();
+ return null;
+ }
+
+ Spine.TrackEntry deathTrack = animState.SetAnimation(deathTrackIndex, deadAnim, false);
+
+ if (deathTrack != null)
+ {
+ activeSkillTracks[deathTrackIndex] = deathTrack;
+
+ if (onComplete != null)
+ trackEntryCallbacks[deathTrack] = onComplete;
+ }
+
+ return deathTrack;
+ }
+
+ private void AddAction(Action action) => runningActions.Add(action);
+ private void RemoveAction(Action action) => runningActions.Remove(action);
+
+ public Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillBase skillBase, bool isSubSkill, Action onComplete = null)
+ {
+ if (skillConfig == null)
+ {
+ Debug.LogError("鎶�鑳介厤缃负绌猴紝鏃犳硶鎾斁鎶�鑳藉姩鐢�");
+ return null;
+ }
+ if (animState == null || skeleton == null)
+ {
+ Debug.LogError("SkeletonGraphic鎴朅nimationState鏈垵濮嬪寲锛屾棤娉曟挱鏀炬妧鑳藉姩鐢�");
+ return null;
+ }
+
+ // 濡傛灉娌℃湁鍔ㄧ敾鍚嶇О锛屼娇鐢ㄦ棤鍔ㄧ敾妯″紡
+ if (string.IsNullOrEmpty(skillConfig.SkillMotionName))
+ {
+ PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
+ return null;
+ }
+
+ Spine.Animation targetAnim = FindAnim(skillConfig.SkillMotionName);
+ if (targetAnim == null)
+ {
+ skillBase.ForceFinished();
+ return null;
+ }
+
+ return ExecuteSkillAnim(skillConfig, skillBase, onComplete, targetAnim, true, isSubSkill);
+ }
+
+ private Spine.TrackEntry ExecuteSkillAnim(SkillConfig skillConfig, SkillBase skillBase, Action onComplete,
+ Spine.Animation targetAnim, bool hasAnim, bool isSubSkill)
+ {
+ bool isPangdeSkill = 1003020 == skillConfig.SkillID;
+
+ int loopCount = skillConfig.LoopCount;
+ int[] activeFrames = skillConfig.ActiveFrames ?? new int[0];
+ int frameCount = activeFrames.Length;
+ float recoveryFrame = skillConfig.RecoveryFrames;
+
+ // 杞ㄩ亾鍒嗛厤绛栫暐锛氫富鎶�鑳界敤 track 0锛屽瓙鎶�鑳戒粠杞ㄩ亾姹犲垎閰�
+ int trackIndex = 0;
+ if (isSubSkill)
+ {
+ if (availableSubTracks != null && availableSubTracks.Count > 0)
{
- currentFrame ++;
-
- if (currentFrame >= triggerFrame[0])
+ trackIndex = availableSubTracks.Dequeue();
+ subSkillTrackMap[skillBase] = trackIndex;
+ }
+ else
+ {
+ // 杞ㄩ亾姹犺�楀敖鎴栨湭鍒濆鍖栵紝鍥為��鍒版棤鍔ㄧ敾妯″紡
+ Debug.LogWarning($"瀛愭妧鑳借建閬撴睜宸叉弧鎴栨湭鍒濆鍖栵紝鎶�鑳絳skillConfig.SkillID}浣跨敤鏃犲姩鐢绘ā寮�");
+ PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
+ return null;
+ }
+ }
+
+ Spine.TrackEntry skillTrack = null;
+
+ if (hasAnim)
+ {
+ skillTrack = animState.SetAnimation(trackIndex, targetAnim, false);
+ if (null == skillTrack)
+ {
+ Debug.LogError($"鎶�鑳� {skillConfig.SkillID} 鍔ㄧ敾璁剧疆澶辫触");
+ // 濡傛灉鏄瓙鎶�鑳戒笖鍒嗛厤浜嗚建閬擄紝闇�瑕佸洖鏀�
+ if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
{
- triggerFrame.RemoveAt(0);
- callback?.Invoke(motionName, currentFrame);
+ if (availableSubTracks != null)
+ availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+ subSkillTrackMap.Remove(skillBase);
+ }
+ return null;
+ }
+
+ // 鍙湁涓绘妧鑳芥墠鏇存柊 currentTrack
+ if (!isSubSkill)
+ currentTrack = skillTrack;
+
+ activeSkillTracks[trackIndex] = skillTrack;
+ }
+
+ playingSkillAnim = true;
+
+ int currentLoop = 0, triggerCount = 0, failCount = 0;
+ bool beginTriggered = false, finalStarted = false, finalEnded = false, middleStarted = false;
+ bool[] triggeredFrames = new bool[frameCount];
+
+ // 鏂板锛氳褰曟妧鑳藉紑濮嬫椂鐨� pausedAccumulated 鍩虹嚎锛岀敤浜庡悗缁绠楄鎶�鑳借嚜韬殑鏆傚仠鏃堕暱
+ float pausedAccumulatedAtStart = pausedAccumulated;
+
+ // startTime 琛ㄧず鎶�鑳�"鏈湴閫昏緫鏃堕棿"鐨勮捣鐐癸紙浠� Time.time 涓哄熀鍑嗭級
+ float startTime = hasAnim ? 0f : Time.time;
+
+ skillBase.OnSkillStart();
+
+ Action frameHandler = null;
+ frameHandler = () =>
+ {
+ if (skillBase.IsFinished())
+ {
+ // 娓呯悊骞堕��鍑猴紙淇濊瘉鐘舵�佷竴鑷达級
+ if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex))
+ {
+ if (activeSkillTracks[trackIndex] == skillTrack)
+ activeSkillTracks.Remove(trackIndex);
+ }
+
+ // 鍥炴敹瀛愭妧鑳借建閬�
+ if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+ {
+ if (availableSubTracks != null)
+ availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+ subSkillTrackMap.Remove(skillBase);
+ }
+
+ // 鍙湁褰撴病鏈夊叾浠栨椿璺冩妧鑳芥椂鎵嶅浣� playingSkillAnim
+ if (activeSkillTracks.Count == 0)
+ playingSkillAnim = false;
+
+ RemoveAction(frameHandler);
+ return;
+ }
+
+ float trackTime = 0f;
+
+ if (hasAnim)
+ {
+ trackTime = skillTrack.TrackTime;
+ }
+ else
+ {
+ // 浣跨敤 pausedAccumulatedAtStart 鏉ヨ绠�"杩欎釜鎶�鑳借嚜寮�濮嬩互鏉ョ殑鏆傚仠鎬绘椂闀�"
+ float adjustedTime = Time.time;
+ float thisSkillPaused = pausedAccumulated - pausedAccumulatedAtStart;
+ if (thisSkillPaused < 0f) thisSkillPaused = 0f; // 淇濋櫓闃叉姢
+
+ // 閫昏緫杩愯鏃堕棿 = 褰撳墠鏃堕棿 - startTime - 鏈妧鑳藉凡鏆傚仠鏃堕暱
+ trackTime = (adjustedTime - startTime - thisSkillPaused) * MotionTimeScale;
+ }
+
+ float currentFrame = trackTime * BattleConst.skillMotionFps;
+
+ if (hasAnim)
+ {
+ // 妫�鏌ュ綋鍓嶈建閬撴槸鍚﹁鏂版妧鑳借鐩�
+ if (!activeSkillTracks.ContainsKey(trackIndex) || activeSkillTracks[trackIndex] != skillTrack)
+ {
+ Debug.LogError("鎶�鑳藉姩鐢昏鎵撴柇锛屽己鍒剁粨鏉� " + skillConfig.SkillID);
+ skillBase.ForceFinished();
+
+ // 娓呯悊骞剁‘淇濈姸鎬佸浣�
+ RemoveAction(frameHandler);
+
+ // 鍥炴敹瀛愭妧鑳借建閬�
+ if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+ {
+ if (availableSubTracks != null)
+ availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+ subSkillTrackMap.Remove(skillBase);
+ }
+
+ if (activeSkillTracks.Count == 0)
+ playingSkillAnim = false;
+ return;
+ }
+
+ if (skillTrack.TrackTime == 0) failCount++;
+ if (failCount > 100)
+ {
+ Debug.LogError("鎶�鑳藉姩鐢绘挱鏀惧け璐ワ紝寮哄埗缁撴潫 " + skillConfig.SkillID);
+ skillBase.ForceFinished();
+ RemoveAction(frameHandler);
+ if (activeSkillTracks.ContainsKey(trackIndex))
+ activeSkillTracks.Remove(trackIndex);
+
+ // 鍥炴敹瀛愭妧鑳借建閬�
+ if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+ {
+ if (availableSubTracks != null)
+ availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+ subSkillTrackMap.Remove(skillBase);
+ }
+
+ if (activeSkillTracks.Count == 0)
+ playingSkillAnim = false;
+ return;
+ }
+ }
+
+ // 鍚勯樁娈靛洖璋冿紙鍘熸湁閫昏緫锛�
+ if (!beginTriggered && currentFrame >= skillConfig.StartupFrames && currentLoop == 0)
+ {
+ beginTriggered = true;
+ skillBase.OnStartSkillFrameEnd();
+ }
+
+ if (!middleStarted && currentFrame >= skillConfig.StartupFrames && currentLoop <= loopCount)
+ {
+ middleStarted = true;
+ skillBase.OnMiddleFrameStart(currentLoop);
+ }
+
+ for (int i = 0; i < frameCount && i < triggeredFrames.Length; i++)
+ {
+ if (!triggeredFrames[i] && currentFrame >= activeFrames[i])
+ {
+ skillBase.OnMiddleFrameEnd(currentLoop, triggerCount++);
+ triggeredFrames[i] = true;
+ }
+ }
+
+ bool allTriggered = Array.TrueForAll(triggeredFrames, x => x);
+
+ if (allTriggered && currentLoop < loopCount)
+ {
+ currentLoop++;
+ Array.Clear(triggeredFrames, 0, frameCount);
+ middleStarted = false;
+
+ if (currentLoop < loopCount)
+ {
+ if (BattleConst.skillMotionFps > 0)
+ {
+ if (hasAnim)
+ {
+ skillTrack.TrackTime = skillConfig.StartupFrames / BattleConst.skillMotionFps;
+ }
+ else
+ {
+ // 涓轰笅涓� loop 閲嶇疆 startTime锛屽苟涓旀洿鏂� pausedAccumulatedAtStart锛堜互淇濇寔鍩虹嚎锛�
+ startTime = Time.time - (skillConfig.StartupFrames / BattleConst.skillMotionFps);
+ pausedAccumulatedAtStart = pausedAccumulated;
+ }
+ }
+ beginTriggered = false;
+ }
+ else
+ {
+ finalStarted = false;
+ finalEnded = false;
+ }
+ }
+
+ if (currentLoop >= loopCount)
+ {
+ if (!finalStarted && currentFrame >= recoveryFrame)
+ {
+ finalStarted = true;
+ skillBase.OnFinalFrameStart();
+ }
+ if (finalStarted && !finalEnded && currentFrame >= recoveryFrame)
+ {
+ finalEnded = true;
+
+ // 娓呯悊鎶�鑳借建閬�
+ if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex))
+ {
+ if (activeSkillTracks[trackIndex] == skillTrack)
+ activeSkillTracks.Remove(trackIndex);
+ }
+
+ // 鍥炴敹瀛愭妧鑳借建閬�
+ if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+ {
+ if (availableSubTracks != null)
+ availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+ subSkillTrackMap.Remove(skillBase);
+ }
+
+ // 鍙湁褰撴病鏈夊叾浠栨椿璺冩妧鑳芥椂鎵嶅浣� playingSkillAnim
+ if (activeSkillTracks.Count == 0)
+ playingSkillAnim = false;
+
+ RemoveAction(frameHandler);
+ onComplete?.Invoke();
+ skillBase.OnFinalFrameEnd();
+ }
+ }
+ };
+
+ AddAction(frameHandler);
+ return skillTrack;
+ }
+
+ private Spine.Animation FindAnim(string animName)
+ {
+ if (string.IsNullOrEmpty(animName)) return null;
+
+ Spine.Animation targetAnim = skeleton.Data.FindAnimation(animName);
+ if (targetAnim == null && skeleton.Data.Animations != null)
+ {
+ for (int i = 0; i < skeleton.Data.Animations.Count; i++)
+ {
+ var anim = skeleton.Data.Animations.Items[i];
+ if (anim?.Name != null && anim.Name.ToLower() == animName.ToLower())
+ {
+ targetAnim = anim;
+ break;
}
}
}
+
+ if (targetAnim == null)
+ Debug.LogError($"鎵句笉鍒板姩鐢�: {animName}");
+
+ return targetAnim;
}
- // 鍔ㄧ敾浜嬩欢
- public Action OnAttackAnimationComplete;
- public Action OnHitAnimationComplete;
- public Action<int> OnAttackHitEvent; //trigger index
+ private void PlaySkillNoAnim(SkillConfig skillConfig, SkillBase skillBase, Action onComplete, bool isSubSkill) =>
+ ExecuteSkillAnim(skillConfig, skillBase, onComplete, null, false, isSubSkill);
- #region 缁勪欢寮曠敤
-
- protected SkeletonGraphic skeletonGraphic;
- protected Spine.AnimationState spineAnimationState;
- protected Spine.Skeleton skeleton;
-
- #endregion
-
- #region 鍔ㄧ敾璁剧疆
-
- // 鍔ㄧ敾娣峰悎鏃堕棿
- protected float defaultMixDuration = 0.2f;
-
- #endregion
-
- protected List<WaitingTask> waitingTaskList = new List<WaitingTask>();
- protected List<WaitingTask> removeList = new List<WaitingTask>();
-
- #region 鍒濆鍖栨柟娉�
-
- /// <summary>
- /// 鍒濆鍖栧姩鐢荤粍浠�
- /// </summary>
- /// <param name="skeletonGraphic">楠ㄩ鍔ㄧ敾缁勪欢</param>
- public virtual void Init(SkeletonGraphic skeletonGraphic)
- {
- this.skeletonGraphic = skeletonGraphic;
-
- if (skeletonGraphic != null)
- {
- spineAnimationState = skeletonGraphic.AnimationState;
- skeleton = skeletonGraphic.Skeleton;
-
- // 璁剧疆鍔ㄧ敾娣峰悎鏃堕棿
- if (spineAnimationState != null)
- {
- spineAnimationState.Data.DefaultMix = defaultMixDuration;
- }
-
- // 鎾斁榛樿鍔ㄧ敾
- PlayAnimation(MotionName.idle, true);
-
- // 璁剧疆鍔ㄧ敾浜嬩欢鐩戝惉
- SetupAnimationHandlers();
- }
- else
- {
- Debug.LogError("缂哄皯SkeletonGraphic缁勪欢!");
- }
- }
-
- #endregion
-
- #region 鍔ㄧ敾鎺у埗
-
- /// <summary>
- /// 鎾斁鎸囧畾鍔ㄧ敾
- /// </summary>
- /// <param name="motionName">鍔ㄧ敾鏋氫妇</param>
- /// <param name="loop">鏄惁寰幆</param>
- /// <returns>鍔ㄧ敾杞ㄩ亾鏉$洰</returns>
- public virtual Spine.TrackEntry PlayAnimation(MotionName motionName, bool loop)
- {
- if (spineAnimationState == null) return null;
-
- // 鐩存帴浣跨敤 ToString() 鑰屼笉鏄皟鐢� GetAnimationName
- return spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
- }
-
- /// <summary>
- /// 鎾斁鎸囧畾鍔ㄧ敾锛堜娇鐢ㄥ瓧绗︿覆鍚嶇О锛�
- /// </summary>
- /// <param name="animationName">鍔ㄧ敾鍚嶇О</param>
- /// <param name="loop">鏄惁寰幆</param>
- /// <returns>鍔ㄧ敾杞ㄩ亾鏉$洰</returns>
- public virtual Spine.TrackEntry PlayAnimation(string animationName, bool loop)
- {
- if (spineAnimationState == null) return null;
-
- return spineAnimationState.SetAnimation(0, animationName, loop);
- }
-
- /// <summary>
- /// 娣诲姞鍔ㄧ敾鍒伴槦鍒�
- /// </summary>
- /// <param name="motionName">鍔ㄧ敾鏋氫妇</param>
- /// <param name="loop">鏄惁寰幆</param>
- /// <param name="delay">寤惰繜鏃堕棿</param>
- /// <returns>鍔ㄧ敾杞ㄩ亾鏉$洰</returns>
- public virtual Spine.TrackEntry AddAnimation(MotionName motionName, bool loop, float delay)
- {
- if (spineAnimationState == null) return null;
-
- // 鐩存帴浣跨敤 ToString() 鑰屼笉鏄皟鐢� GetAnimationName
- return spineAnimationState.AddAnimation(0, motionName.ToString(), loop, delay);
- }
-
- /// <summary>
- /// 娣诲姞鍔ㄧ敾鍒伴槦鍒楋紙浣跨敤瀛楃涓插悕绉帮級
- /// </summary>
- /// <param name="animationName">鍔ㄧ敾鍚嶇О</param>
- /// <param name="loop">鏄惁寰幆</param>
- /// <param name="delay">寤惰繜鏃堕棿</param>
- /// <returns>鍔ㄧ敾杞ㄩ亾鏉$洰</returns>
- public virtual Spine.TrackEntry AddAnimation(string animationName, bool loop, float delay)
- {
- if (spineAnimationState == null) return null;
-
- return spineAnimationState.AddAnimation(0, animationName, loop, delay);
- }
-
- /// <summary>
- /// 璁剧疆鍔ㄧ敾浜嬩欢鐩戝惉
- /// </summary>
protected virtual void SetupAnimationHandlers()
{
- if (spineAnimationState == null) return;
-
- // 鐩戝惉鍔ㄧ敾瀹屾垚浜嬩欢
- spineAnimationState.Complete += OnAnimationComplete;
+ if (animState != null)
+ animState.Complete += OnAnimationComplete;
}
-
- /// <summary>
- /// 鍔ㄧ敾瀹屾垚浜嬩欢澶勭悊
- /// </summary>
+
protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry)
{
- string animation = trackEntry.Animation.Name;
-
- // 鏀诲嚮鍔ㄧ敾瀹屾垚鍚庢仮澶嶅埌寰呮満鐘舵��
- if (animation == MotionName.atk1.ToString() ||
- animation == MotionName.atk2.ToString())
+ if (trackEntry?.Animation?.Name == null) return;
+
+ string animName = trackEntry.Animation.Name.ToLower();
+
+ if (AttackMotionList.Contains(animName))
{
OnAttackAnimationComplete?.Invoke();
PlayAnimation(MotionName.idle, true);
}
- // 鍙椾激鍔ㄧ敾瀹屾垚鍚庢仮澶嶅埌寰呮満鐘舵��
- else if (animation == MotionName.hit.ToString())
+ else if (animName == MotionName.hit.ToString().ToLower())
{
OnHitAnimationComplete?.Invoke();
PlayAnimation(MotionName.idle, true);
}
+
+ if (trackEntryCallbacks.TryGetValue(trackEntry, out var callback))
+ {
+ trackEntryCallbacks.Remove(trackEntry);
+ callback?.Invoke();
+ }
+ }
+
+ public void SetControledAnimation()
+ {
+ // 鍙楀埌纭帶鐨勬椂鍊欙紝淇濇寔鍙楀嚮鍔ㄧ敾鐨勭涓夊抚锛岀洿鍒版帶鍒剁粨鏉� 鎴栬�呮渶鍚庝竴鍑绘浜★紝绉婚櫎鎺у埗鏁堟灉鍚庯紝鎭㈠鍒板緟鏈虹姸鎬佹垨鑰呮挱鏀炬浜″姩鐢�
+ // 杩欓噷鏄彈鍒扮‖鎺ф椂鍊� 闇�瑕佽〃鐜扮殑鍔ㄧ敾
+
+ var entry = PlayAnimation(MotionName.hit, false);
+ float threeFrameTrackTime = 3f / BattleConst.skillMotionFps;
+ entry.TrackTime = threeFrameTrackTime;
+ entry.TimeScale = 0;
+
+ isUnderControl = true;
+
}
- /// <summary>
- /// 鍔ㄧ敾浜嬩欢澶勭悊
- /// </summary>
- protected virtual void OnTriggerHitEvent(MotionName motionName, int hitIndex)
+ public void CancelControledAnimation()
{
- OnAttackHitEvent?.Invoke(hitIndex);
- }
-
- // 鎷撳睍浜嗘挱鏀惧姩鐢绘柟娉曪紝娣诲姞浜嗚Е鍙戝抚鐨勫姛鑳斤紝鍦ㄦ敾鍑诲姩鐢讳腑澶氭鏀诲嚮鐨勮Е鍙戝抚
- // 渚嬪锛氭敾鍑诲姩鐢绘湁涓夋锛岀涓�娈垫敾鍑诲湪绗�1甯цЕ鍙戯紝绗簩娈垫敾鍑诲湪绗�10甯цЕ鍙戯紝绗笁娈垫敾鍑诲湪绗�20甯цЕ鍙�
- // 閭d箞triggerFrame灏卞簲璇ユ槸[1, 10, 20]
- public virtual void PlayAnimationEx(MotionName motionName, bool loop, List<int> triggerFrame = null)
- {
- PlayAnimation(motionName, loop);
- if (triggerFrame != null && triggerFrame.Count >= 0)
- {
- AddWaitingTask(triggerFrame, motionName);
- }
- }
-
- protected void AddWaitingTask(List<int> triggerFrame, MotionName motionName)
- {
- if (triggerFrame != null && triggerFrame.Count > 0)
- {
- WaitingTask waitingTask = new WaitingTask(triggerFrame, motionName, OnTriggerHitEvent);
- waitingTaskList.Add(waitingTask);
- }
+ // 纭帶缁撴潫锛屾仮澶嶅姩鐢绘挱鏀�
+ isUnderControl = false;
+ PlayAnimation(MotionName.idle, true);
}
public virtual void Run()
{
- foreach (WaitingTask waitingTask in waitingTaskList)
- {
- waitingTask.Run();
+ for (int i = runningActions.Count - 1; i >= 0; i--)
+ runningActions[i]?.Invoke();
- if (waitingTask.IsFinished())
- {
- removeList.Add(waitingTask);
- }
- }
-
- foreach (WaitingTask waitingTask in removeList)
- {
- waitingTaskList.Remove(waitingTask);
- }
-
- removeList.Clear();
+ illusionShadow?.Run();
}
- #endregion
-
+
+ public virtual void Pause()
+ {
+ if (skeletonAnim != null) skeletonAnim.timeScale = 0f;
+
+ // 璁板綍鍗曟鏆傚仠寮�濮嬫椂鍒�
+ pauseStart = Time.time;
+ // 鍏煎鏃у瓧娈碉紙淇濈暀浣嗕笉鍐嶇敤浜庣疮绉�昏緫锛�
+ pauseTime = Time.time;
+ }
+
+ public virtual void Resume()
+ {
+ if (skeletonAnim != null) skeletonAnim.timeScale = MotionTimeScale;
+
+ // 绱Н鏆傚仠鏃堕暱锛堝鏋滄浘璁板綍杩� pauseStart锛�
+ if (pauseStart > 0f)
+ {
+ pausedAccumulated += (Time.time - pauseStart);
+ pauseStart = 0f;
+ }
+
+ // 淇濇寔鏃у瓧娈典互鍏煎鐜版湁浠g爜锛堜絾瀹為檯鏃堕棿淇浣跨敤 pausedAccumulated锛�
+ resumeTime = Time.time;
+ }
+
+ public void HaveRest()
+ {
+ trackEntryCallbacks.Clear();
+ runningActions.Clear();
+ activeSkillTracks.Clear();
+
+ // 閲嶇疆瀛愭妧鑳借建閬撴睜
+ if (availableSubTracks == null)
+ availableSubTracks = new Queue<int>();
+ else
+ availableSubTracks.Clear();
+
+ subSkillTrackMap.Clear();
+ for (int i = 1; i <= 8; i++)
+ availableSubTracks.Enqueue(i);
+
+ playingSkillAnim = false;
+ PlayAnimation(MotionName.idle, true);
+ }
+
+ public void SetSpeedRatio(float ratio)
+ {
+ MotionTimeScale = ratio;
+ if (skeletonAnim != null) skeletonAnim.timeScale = ratio;
+ }
+
+ public void ShowIllusionShadow(bool isVisible, Color color = default)
+ {
+ if (illusionShadow != null)
+ {
+ illusionShadow.SetSkeletonAnimation(skeletonAnim);
+ illusionShadow.Show(isVisible, color);
+ }
+ }
}
\ No newline at end of file
--
Gitblit v1.8.0