HonorLee 4 months ago
parent
commit
6a77009a63
4 changed files with 327 additions and 264 deletions
  1. 100 93
      CrossgateToolkit/Anime.cs
  2. 109 57
      CrossgateToolkit/AnimePlayer.cs
  3. 115 114
      CrossgateToolkit/Audio.cs
  4. 3 0
      CrossgateToolkit/Graphic.cs

+ 100 - 93
CrossgateToolkit/Anime.cs

@@ -30,7 +30,9 @@ namespace CrossgateToolkit
         //2 bytes   未知字节
         public byte[] Unknow;
         //动画数据  Direction -> ActionType -> AnimeData
-        public Dictionary<int, Dictionary<int, AnimeDetail>> AnimeDatas = new Dictionary<int, Dictionary<int, AnimeDetail>>();
+        public Dictionary<int, Dictionary<int, AnimeDetail>> AnimeDatas;
+        // 数据读取对象
+        public BinaryReader DataReader;
     }
 
     //动画帧数据
@@ -123,7 +125,7 @@ namespace CrossgateToolkit
         public enum ActionType
         {
             NULL        = -1,
-            Stand       = 0,
+            Idle       = 0,
             Walk        = 1,
             BeforeRun   = 2,
             Run         = 3,
@@ -179,101 +181,22 @@ namespace CrossgateToolkit
             for (int i = 0; i < DataLength; i++)
             {
                 //初始化对象
-                AnimeInfo animeInfo = new AnimeInfo();
-                animeInfo.Version = Version;
-                animeInfo.Serial = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0);
-                // Debug.Log(animeInfo.Serial);
-                animeInfo.Addr = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0);
-                animeInfo.ActionCount = infoFileReader.ReadUInt16();
-                animeInfo.Unknow = infoFileReader.ReadBytes(2);
-                if (animeInfo.Addr > dataFileStream.Length) break;
-                dataFileStream.Position = animeInfo.Addr;
-                for (int j = 0; j < animeInfo.ActionCount; j++)
+                AnimeInfo animeInfo = new AnimeInfo
                 {
-                    
-                    // 高版本标识
-                    bool isHighVersion = false;
-                    dataFileStream.Position += 16;
-                    if(dataFileReader.ReadBytes(4).SequenceEqual(highVersionFlag)) isHighVersion = true;
-                    dataFileStream.Position -= 20;
-                    
-                    AnimeDetail animeData = new AnimeDetail();
-                    animeData.Version = Version;
-                    animeData.Serial = animeInfo.Serial;
-                    animeData.Direction = dataFileReader.ReadUInt16();
-                    animeData.ActionType = dataFileReader.ReadUInt16();
-                    animeData.CycleTime = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
-                    animeData.FrameCount = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
-                    
-                    // 高版本
-                    if (isHighVersion)
-                    {
-                        animeData.IsHighVersion = true;
-                        animeData.Palet = dataFileReader.ReadUInt16();
-                        int flag = dataFileReader.ReadUInt16();
-                        if (flag > 0)
-                        {
-                            animeData.FLAG = new AnimeFlag();
-                            if ((flag & 1) == (1 << 0)) animeData.FLAG.REVERSE_X = true;
-                            if ((flag & 2) == (1 << 1)) animeData.FLAG.REVERSE_Y = true;
-                            if ((flag & 4) == (1 << 2)) animeData.FLAG.LOCK_PAL = true;
-                            if ((flag & 8) == (1 << 3)) animeData.FLAG.LIGHT_THROUGH = true;    
-                        }
-                        
-                        animeData.FLAG_END = dataFileReader.ReadBytes(4);
-                    }
-                    animeData.AnimeFrameInfos = new List<AnimeFrameInfo>();
-                    
-                    // if (animeInfo.Index == 101201) Debug.Log("----------------------------------");
-                    for (int k = 0; k < animeData.FrameCount; k++)
-                    {
-                        byte[] frameBytes = dataFileReader.ReadBytes(10);
-                        if (frameBytes.Length <10) break;
-                        BinaryReader frameReader = new BinaryReader(new MemoryStream(frameBytes));
-                        AnimeFrameInfo animeFrameInfo = new AnimeFrameInfo();
-                        //GraphicIndex序号
-                        animeFrameInfo.GraphicIndex = BitConverter.ToUInt32(frameReader.ReadBytes(4),0);
-                        animeFrameInfo.OffsetX = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
-                        animeFrameInfo.OffsetY = BitConverter.ToInt16(frameReader.ReadBytes(2), 0);
-                        
-                        //标识位
-                        int flag = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
-
-                        if (flag>20000)
-                        {
-                            //击打判定
-                            animeFrameInfo.Effect = EffectType.Hit;
-                            animeFrameInfo.AudioIndex = flag - 20000;
-                        }
-                        else if(flag>10000)
-                        {
-                            //攻击动作结束判定
-                            animeFrameInfo.Effect = EffectType.HitOver;
-                            animeFrameInfo.AudioIndex = flag - 10000;
-                        }
-                        else
-                        {
-                            animeFrameInfo.AudioIndex = flag;
-                        }
-                        animeData.AnimeFrameInfos.Add(animeFrameInfo);
-                    }
-                    animeData.FrameCount = (uint) animeData.AnimeFrameInfos.Count;
-
-                    if (!animeInfo.AnimeDatas.ContainsKey(animeData.Direction))
-                        animeInfo.AnimeDatas.Add(animeData.Direction, new Dictionary<int, AnimeDetail>());
-
-                    animeInfo.AnimeDatas[animeData.Direction][animeData.ActionType] = animeData;
-                    
-                    _animeInfoCache[animeInfo.Serial] = animeInfo;
-                }
-
+                    Version = Version,
+                    Serial = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0),
+                    Addr = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0),
+                    ActionCount = infoFileReader.ReadUInt16(),
+                    Unknow = infoFileReader.ReadBytes(2)
+                };
+                if (animeInfo.Addr > dataFileStream.Length) break;
+                
+                animeInfo.DataReader = dataFileReader;
+                _animeInfoCache[animeInfo.Serial] = animeInfo;
             }
             infoFileReader.Dispose();
             infoFileReader.Close();
-            dataFileReader.Dispose();
-            dataFileReader.Close();
             infoFileStream.Close();
-            dataFileStream.Close();
             
             Debug.Log("[CGTool] 加载AnimeInfo - 文件: [" +
                       // (Graphic.Flag_HighVersion[Version] ? "H" : "N") + "] [" +
@@ -281,11 +204,94 @@ namespace CrossgateToolkit
                       animeInfoFile.Name +
                       " 动画总量: " + DataLength);
         }
+
+        private static void ReadAnimeData(AnimeInfo animeInfo)
+        {
+            animeInfo.DataReader.BaseStream.Position = animeInfo.Addr;
+            animeInfo.AnimeDatas = new Dictionary<int, Dictionary<int, AnimeDetail>>();
+            for (int j = 0; j < animeInfo.ActionCount; j++)
+            {
+                
+                // 高版本标识
+                bool isHighVersion = false;
+                animeInfo.DataReader.BaseStream.Position += 16;
+                if(animeInfo.DataReader.ReadBytes(4).SequenceEqual(highVersionFlag)) isHighVersion = true;
+                animeInfo.DataReader.BaseStream.Position -= 20;
+                
+                AnimeDetail animeData = new AnimeDetail();
+                animeData.Version = animeInfo.Version;
+                animeData.Serial = animeInfo.Serial;
+                animeData.Direction = animeInfo.DataReader.ReadUInt16();
+                animeData.ActionType = animeInfo.DataReader.ReadUInt16();
+                animeData.CycleTime = BitConverter.ToUInt32(animeInfo.DataReader.ReadBytes(4),0);
+                animeData.FrameCount = BitConverter.ToUInt32(animeInfo.DataReader.ReadBytes(4),0);
+                
+                // 高版本
+                if (isHighVersion)
+                {
+                    animeData.IsHighVersion = true;
+                    animeData.Palet = animeInfo.DataReader.ReadUInt16();
+                    int flag = animeInfo.DataReader.ReadUInt16();
+                    if (flag > 0)
+                    {
+                        animeData.FLAG = new AnimeFlag();
+                        if ((flag & 1) == (1 << 0)) animeData.FLAG.REVERSE_X = true;
+                        if ((flag & 2) == (1 << 1)) animeData.FLAG.REVERSE_Y = true;
+                        if ((flag & 4) == (1 << 2)) animeData.FLAG.LOCK_PAL = true;
+                        if ((flag & 8) == (1 << 3)) animeData.FLAG.LIGHT_THROUGH = true;    
+                    }
+                    
+                    animeData.FLAG_END = animeInfo.DataReader.ReadBytes(4);
+                }
+                animeData.AnimeFrameInfos = new List<AnimeFrameInfo>();
+                
+                // if (animeInfo.Index == 101201) Debug.Log("----------------------------------");
+                for (int k = 0; k < animeData.FrameCount; k++)
+                {
+                    byte[] frameBytes = animeInfo.DataReader.ReadBytes(10);
+                    if (frameBytes.Length <10) break;
+                    BinaryReader frameReader = new BinaryReader(new MemoryStream(frameBytes));
+                    AnimeFrameInfo animeFrameInfo = new AnimeFrameInfo();
+                    //GraphicIndex序号
+                    animeFrameInfo.GraphicIndex = BitConverter.ToUInt32(frameReader.ReadBytes(4),0);
+                    animeFrameInfo.OffsetX = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
+                    animeFrameInfo.OffsetY = BitConverter.ToInt16(frameReader.ReadBytes(2), 0);
+                    
+                    //标识位
+                    int flag = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
+            
+                    if (flag>20000)
+                    {
+                        //击打判定
+                        animeFrameInfo.Effect = EffectType.Hit;
+                        animeFrameInfo.AudioIndex = flag - 20000;
+                    }
+                    else if(flag>10000)
+                    {
+                        //攻击动作结束判定
+                        animeFrameInfo.Effect = EffectType.HitOver;
+                        animeFrameInfo.AudioIndex = flag - 10000;
+                    }
+                    else
+                    {
+                        animeFrameInfo.AudioIndex = flag;
+                    }
+                    animeData.AnimeFrameInfos.Add(animeFrameInfo);
+                }
+                animeData.FrameCount = (uint) animeData.AnimeFrameInfos.Count;
+            
+                if (!animeInfo.AnimeDatas.ContainsKey(animeData.Direction))
+                    animeInfo.AnimeDatas.Add(animeData.Direction, new Dictionary<int, AnimeDetail>());
+            
+                animeInfo.AnimeDatas[animeData.Direction][animeData.ActionType] = animeData;
+            }
+        }
         
         //获取动画数据信息
         public static AnimeInfo GetAnimeInfo(uint serial)
         {
-            _animeInfoCache.TryGetValue(serial, out var animeInfo);
+            _animeInfoCache.TryGetValue(serial, out AnimeInfo animeInfo);
+            if (animeInfo is { AnimeDatas: null }) ReadAnimeData(animeInfo);
             return animeInfo;
         }
 
@@ -294,6 +300,7 @@ namespace CrossgateToolkit
         {
             AnimeInfo animeInfo = GetAnimeInfo(serial);
             if (animeInfo == null) return null;
+            
             if (animeInfo.AnimeDatas.ContainsKey((int)Direction))
             {
                 if (animeInfo.AnimeDatas[(int) Direction].ContainsKey((int) Action))

+ 109 - 57
CrossgateToolkit/AnimePlayer.cs

@@ -10,7 +10,6 @@
 
 using System.Collections.Generic;
 using UnityEngine;
-using UnityEngine.Serialization;
 using UnityEngine.UI;
 
 namespace CrossgateToolkit
@@ -59,6 +58,7 @@ namespace CrossgateToolkit
             public float FrameRate;
             public AnimeDetail AnimeDetail;
             public AnimeCallback onFinishCallback;
+            public AnimeEffectListener onEffectListener;
             public int CurrentFrame = 0;
             public bool KeepFrame = false;
         }
@@ -71,9 +71,25 @@ namespace CrossgateToolkit
         
         //是否播放
         private bool isPlayable;
+        // private bool isPlayable
+        // {
+        //     get => _isPlayable;
+        //     set
+        //     {
+        //         _isPlayable = value;
+        //         if (_isPlayable)
+        //         {
+        //             _timer = Time.time * 1000;
+        //         }
+        //         else
+        //         {
+        //             Debug.Log("set isPlayable  " + isPlayable + "  "+_currentAnime?.actionType);
+        //         }
+        //     }
+        // }
         
         //待播放队列
-        private Queue<AnimeOption> _animeQueue = new Queue<AnimeOption>();
+        private readonly List<AnimeOption> _animeQueue = new List<AnimeOption>();
         
         //计时器
         private float _timer;
@@ -102,11 +118,9 @@ namespace CrossgateToolkit
         
         //绑定RectTransform
         private RectTransform _rectTransform;
-        //绑定BoxCollider2D(可选)
-        private BoxCollider2D _boxCollider2D;
         
         //动画动作帧监听
-        public AnimeEffectListener onEffectListener;
+        // public AnimeEffectListener onEffectListener;
         public AnimeAudioListener onAudioListener;
         //鼠标移入事件监听
         public MouseListener onMouseEnterListener;
@@ -147,13 +161,13 @@ namespace CrossgateToolkit
         //鼠标移入监听
         private void OnMouseEnter()
         {
-            if(onMouseEnterListener!=null) onMouseEnterListener(this);
+            onMouseEnterListener?.Invoke(this);
         }
 
         //鼠标移出监听
         private void OnMouseExit()
         {
-            if(onMouseExitListener!=null) onMouseExitListener(this);
+            onMouseExitListener?.Invoke(this);
         }
         
         // 使用Image模式渲染
@@ -180,11 +194,12 @@ namespace CrossgateToolkit
                 }
                 Anime.DirectionType direction =
                     _currentAnime?.Direction ?? Anime.DirectionType.North;
-                Anime.ActionType actionType = _currentAnime?.actionType ?? Anime.ActionType.Stand;
+                Anime.ActionType actionType = _currentAnime?.actionType ?? Anime.ActionType.Idle;
                 Anime.PlayType playType = _currentAnime?.playType ?? Anime.PlayType.Loop;
                 float speed = _currentAnime?.Speed ?? 1f;
                 AnimeCallback onFinishCallback = _currentAnime?.onFinishCallback;
-                play(value, direction, actionType, playType, speed, onFinishCallback);
+                AnimeEffectListener onEffectListener = _currentAnime?.onEffectListener;
+                play(value, direction, actionType, playType, speed, onEffectListener,onFinishCallback);
             }
         }
         
@@ -237,28 +252,23 @@ namespace CrossgateToolkit
         /// <param name="ActionType">动画动作</param>
         /// <param name="PlayType">播放类型</param>
         /// <param name="Speed">播放速度,以 1s 为基准,根据动画帧率计算实际播放周期时长</param>
+        /// <param name="onEffectListener">动画动作帧监听</param>
         /// <param name="onFinishCallback">动画结束回调</param>
         /// <returns>AnimePlayer</returns>
-        public AnimePlayer play(uint Serial, Anime.DirectionType Direction = Anime.DirectionType.North,
-            Anime.ActionType actionType = Anime.ActionType.Stand, Anime.PlayType playType = Anime.PlayType.Once,
-            float Speed = 1f, AnimeCallback onFinishCallback = null)
+        public AnimePlayer play(uint serial, Anime.DirectionType Direction = Anime.DirectionType.North, 
+            Anime.ActionType actionType = Anime.ActionType.Idle, Anime.PlayType playType = Anime.PlayType.Once,
+            float Speed = 1f,AnimeEffectListener onEffectListener = null,AnimeCallback onFinishCallback = null)
         {
-            if (_spriteRenderer == null)
-            {
-                // Debug.Log("AnimePlayer:SpriteRenderer is null");
-                return this;
-            }
-            AnimeOption animeOption = CreateAnimeOption(Serial, Direction, actionType, playType, Speed, onFinishCallback);
+            AnimeOption animeOption = CreateAnimeOption(serial, Direction, actionType, playType, Speed,onEffectListener, onFinishCallback);
             if (animeOption == null)
             {
-                if (onFinishCallback != null) onFinishCallback(actionType);
+                onFinishCallback?.Invoke(actionType);
                 // Debug.Log("AnimePlayer:AnimeOption create failed");
                 return this;
             }
             //清空播放队列
             _animeQueue.Clear();
-            //播放
-            _currentSerial = Serial;
+            _animeQueue.Add(animeOption);
             _play(animeOption);
             
             //链式调用,后续可通过nextPlay方法添加动画到播放队列
@@ -266,32 +276,40 @@ namespace CrossgateToolkit
         }
 
         //播放动画
-        public AnimePlayer play(uint Serial, Anime.PlayType playType, float speed = 1f,
-            AnimeCallback onFinishCallback = null)
+        public AnimePlayer play(uint serial, Anime.PlayType playType, float speed = 1f,AnimeEffectListener onEffectListener = null,AnimeCallback onFinishCallback = null)
+        {
+            return play(serial,Anime.DirectionType.North,Anime.ActionType.Idle,playType,speed,onEffectListener,onFinishCallback);
+        }
+        
+        //不改变Serial情况下播放动画
+        public AnimePlayer play(Anime.DirectionType directionType,Anime.ActionType actionType,Anime.PlayType playType,float Speed=1f,AnimeEffectListener onEffectListener=null,AnimeCallback onFinishCallback=null)
         {
-            return play(Serial,Anime.DirectionType.North,Anime.ActionType.Stand,playType,speed,onFinishCallback);
+            return play(_currentSerial, directionType, actionType, playType,
+                Speed,onEffectListener, onFinishCallback);
         }
 
         //播放一次
-        public AnimePlayer playOnce(Anime.DirectionType directionType,Anime.ActionType actionType,float Speed=1f,AnimeCallback onFinishCallback=null)
+        public AnimePlayer playOnce(Anime.DirectionType directionType,Anime.ActionType actionType,float Speed=1f,AnimeEffectListener onEffectListener=null,AnimeCallback onFinishCallback=null)
         {
             return play(_currentSerial, directionType, actionType, Anime.PlayType.Once,
-                Speed, onFinishCallback);
+                Speed, onEffectListener,onFinishCallback);
         }
         
         //播放循环
-        public AnimePlayer playLoop(Anime.DirectionType directionType,Anime.ActionType actionType,float Speed=1f,AnimeCallback onFinishCallback=null)
+        public AnimePlayer playLoop(Anime.DirectionType directionType,Anime.ActionType actionType,float Speed=1f,AnimeEffectListener onEffectListener=null,AnimeCallback onFinishCallback=null)
         {
             return play(_currentSerial, directionType, actionType, Anime.PlayType.Loop,
-                Speed, onFinishCallback);
+                Speed, onEffectListener,onFinishCallback);
         }
 
         //调整动画方向
         public void changeDirection(Anime.DirectionType directionType)
         {
             if (directionType == _currentAnime.Direction || directionType == Anime.DirectionType.NULL) return;
+            // _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, directionType, _currentAnime.actionType,
+            //     _currentAnime.playType, _currentAnime.Speed, _currentAnime.onEffectListener,_currentAnime.onFinishCallback);
             _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, directionType, _currentAnime.actionType,
-                _currentAnime.playType, _currentAnime.Speed, _currentAnime.onFinishCallback);
+                _currentAnime.playType, _currentAnime.Speed);
             _play(_currentAnime);
         }
         public Anime.DirectionType DirectionType
@@ -310,8 +328,10 @@ namespace CrossgateToolkit
         public void changeActionType(Anime.ActionType actionType)
         {
             if (actionType == _currentAnime.actionType) return;
+            // _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, _currentAnime.Direction,actionType,
+            //     _currentAnime.playType, _currentAnime.Speed, _currentAnime.onEffectListener,_currentAnime.onFinishCallback);
             _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, _currentAnime.Direction,actionType,
-                _currentAnime.playType, _currentAnime.Speed, _currentAnime.onFinishCallback);
+                _currentAnime.playType, _currentAnime.Speed);
             _play(_currentAnime);
         }
         public Anime.ActionType ActionType
@@ -332,6 +352,8 @@ namespace CrossgateToolkit
             isPlayable = false;
             _currentAnime = null;
             
+            // Debug.Log("AnimePlayer:play " + animeOption.AnimeSerial + "  " + animeOption.actionType);
+            
             AnimeFrame[] frames = new AnimeFrame[animeOption.AnimeDetail.FrameCount];
 
             if (isFrameBatch)
@@ -385,12 +407,15 @@ namespace CrossgateToolkit
                 }
             }
             
-
+            
             _currentAnime = animeOption;
+            _currentSerial = animeOption.AnimeSerial;
             _frames = frames;
             // _currentAnime.CurrentFrame = _currentAnime.CurrentFrame;
-            isPlayable = true;
+            _delay = 0;
             gameObject.SetActive(true);
+            
+            isPlayable = true;
             UpdateFrame();
         }
 
@@ -400,19 +425,25 @@ namespace CrossgateToolkit
             _delay = delayTime*1000;
         }
 
+        //停止播放
         public void Stop()
         {
             isPlayable = false;
             _currentAnime = null;
             _frames = null;
-            _currentAnime.CurrentFrame = 0;
             gameObject.SetActive(false);
         }
 
+        //暂停播放
         public void Pause()
         {
             isPlayable = false;
         }
+        //恢复播放
+        public void Resume()
+        {
+            isPlayable = true;
+        }
 
         //修改播放类型---重复方法--考虑删掉
         public void ChangePlayType(Anime.PlayType playType)
@@ -422,37 +453,38 @@ namespace CrossgateToolkit
         }
 
         //创建动画配置
-        private AnimeOption CreateAnimeOption(uint Serial, Anime.DirectionType Direction, Anime.ActionType ActionType,
-            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f, AnimeCallback onFinishCallback = null)
+        private AnimeOption CreateAnimeOption(uint serial, Anime.DirectionType Direction, Anime.ActionType actionType,
+            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f,AnimeEffectListener onEffectListener = null, AnimeCallback onFinishCallback = null)
         {
-            AnimeDetail animeDetail = Anime.GetAnimeDetail(Serial, Direction, ActionType);
+            AnimeDetail animeDetail = Anime.GetAnimeDetail(serial, Direction, actionType);
             if (animeDetail == null)
             {
-                // Debug.Log("AnimePlayer:AnimeDetail is null");
+                // Debug.Log("AnimePlayer:AnimeDetail [" + serial + "] is null");
                 return null;
             }
             AnimeOption animeOption = new AnimeOption()
             {
-                AnimeSerial = Serial,
+                AnimeSerial = serial,
                 Direction = Direction,
-                actionType = ActionType,
+                actionType = actionType,
                 playType = playType,
                 Speed = Speed,
                 FrameRate = animeDetail.CycleTime / Speed / animeDetail.FrameCount,
                 AnimeDetail = animeDetail,
+                onEffectListener = onEffectListener,
                 onFinishCallback = onFinishCallback,
             };
             return animeOption;
         }
 
         //加入链式动画播放队列
-        public AnimePlayer nextPlay(uint Serial, Anime.DirectionType Direction, Anime.ActionType ActionType,
-            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f, AnimeCallback onFinishCallback = null)
+        public AnimePlayer nextPlay(uint serial, Anime.DirectionType Direction, Anime.ActionType actionType,
+            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f, AnimeEffectListener onEffectListener=null, AnimeCallback onFinishCallback = null)
         {
-            AnimeOption animeOption = CreateAnimeOption(Serial, Direction, ActionType, playType, Speed, onFinishCallback);
+            AnimeOption animeOption = CreateAnimeOption(serial, Direction, actionType, playType, Speed, onEffectListener,onFinishCallback);
             if (animeOption == null)
             {
-                if (onFinishCallback != null) onFinishCallback(ActionType);
+                onFinishCallback?.Invoke(actionType);
                 return this;
             }
             if (_animeQueue.Count == 0)
@@ -461,17 +493,17 @@ namespace CrossgateToolkit
             }
             else
             {
-                _animeQueue.Enqueue(animeOption);    
+                _animeQueue.Add(animeOption);    
             }
             
             return this;
         }
         
         //加入链式动画播放队列
-        public AnimePlayer nextPlay(Anime.DirectionType Direction, Anime.ActionType ActionType,
-            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f, AnimeCallback onFinishCallback = null)
+        public AnimePlayer nextPlay(Anime.DirectionType Direction, Anime.ActionType actionType,
+            Anime.PlayType playType=Anime.PlayType.Once, float Speed = 1f,  AnimeEffectListener onEffectListener=null, AnimeCallback onFinishCallback = null)
         {
-            return nextPlay(_currentSerial, Direction, ActionType, playType, Speed, onFinishCallback);
+            return nextPlay(_currentSerial, Direction, actionType, playType, Speed, onEffectListener, onFinishCallback);
         }
         
         // 保持当前帧并切换动画方向(特殊情况如被暴击或击飞后保持受伤帧旋转)
@@ -479,9 +511,12 @@ namespace CrossgateToolkit
         {
             if (directionType == _currentAnime.Direction || directionType == Anime.DirectionType.NULL) return;
             int currentFrame = _currentAnime.CurrentFrame;
+            // _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, directionType, _currentAnime.actionType,
+            //     _currentAnime.playType, _currentAnime.Speed, _currentAnime.onEffectListener,_currentAnime.onFinishCallback);
             _currentAnime = CreateAnimeOption(_currentAnime.AnimeSerial, directionType, _currentAnime.actionType,
-                _currentAnime.playType, _currentAnime.Speed, _currentAnime.onFinishCallback);
-            _currentAnime.CurrentFrame = currentFrame;
+                _currentAnime.playType, _currentAnime.Speed);
+            _currentAnime.CurrentFrame = --currentFrame;
+                
             _currentAnime.KeepFrame = true;
             _play(_currentAnime);
         }
@@ -489,8 +524,10 @@ namespace CrossgateToolkit
         //更新计算
         private void Update()
         {
+            
+            if (!isPlayable || _currentAnime==null) return;
             float now = Time.time * 1000;
-            if (_currentAnime != null && (now - _timer - _delay) >= _currentAnime.FrameRate) UpdateFrame();
+            if ((now - _timer - _delay) >= _currentAnime.FrameRate) UpdateFrame();
         }
 
         //更新帧
@@ -502,43 +539,56 @@ namespace CrossgateToolkit
             //动画结束
             if (_currentAnime.CurrentFrame >= _currentAnime.AnimeDetail.FrameCount)
             {
-                if(_currentAnime.onFinishCallback!=null) _currentAnime.onFinishCallback(_currentAnime.actionType);
                 //循环播放
                 if (_currentAnime.playType == Anime.PlayType.Loop)
                 {
+                    _currentAnime.onFinishCallback?.Invoke(_currentAnime.actionType);
                     _currentAnime.CurrentFrame = 0;
-                }else if (_currentAnime.playType == Anime.PlayType.Once || _currentAnime.playType == Anime.PlayType.OnceAndDestroy)
+                }else if (_currentAnime.playType is Anime.PlayType.Once or Anime.PlayType.OnceAndDestroy)
                 {
+                    _animeQueue.RemoveAt(0);
                     if (_currentAnime.playType == Anime.PlayType.OnceAndDestroy)
                     {
                         _spriteRenderer.sprite = null;
                         _imageRenderer.sprite = null;
                         _rectTransform.sizeDelta = Vector2.zero;
+                        _currentAnime.onFinishCallback?.Invoke(_currentAnime.actionType);
                         gameObject.SetActive(false);
+                        return;
                     }
                     //播放下一个动画
                     if(_animeQueue.Count>0)
                     {
-                        AnimeOption animeOption = _animeQueue.Dequeue();
+                        _currentAnime.onFinishCallback?.Invoke(_currentAnime.actionType);
+                        AnimeOption animeOption = _animeQueue[0];
                         _play(animeOption);
                         return;
                     }else
                     {
                         if (_currentAnime.KeepFrame)
                         {
-                            _currentAnime.CurrentFrame--;
+                            _currentAnime.onFinishCallback?.Invoke(_currentAnime.actionType);
+                            // _currentAnime.CurrentFrame--;
                         }
                         else
                         {
                             isPlayable = false;
+                            _currentAnime.onFinishCallback?.Invoke(_currentAnime.actionType);
                             return;
                         }
+                        
                     }
+                    
                 }
+                
             }
             
             //问题帧自动跳过
-            if (_currentAnime.CurrentFrame<_frames.Length && _frames[_currentAnime.CurrentFrame] == null) return;
+            if (_currentAnime.CurrentFrame < _frames.Length && _frames[_currentAnime.CurrentFrame] == null)
+            {
+                _currentAnime.CurrentFrame++;
+                return;
+            }
             
             //根据当前帧Sprite动态调整对象大小
             float width = _frames[_currentAnime.CurrentFrame].Sprite.rect.width * 1f;
@@ -605,9 +655,11 @@ namespace CrossgateToolkit
             _timer = Time.time * 1000;
             
             //动画事件帧监听
-            if(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.Effect >0 && onEffectListener!=null) onEffectListener(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.Effect);
+            if (_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.Effect > 0)
+                _currentAnime.onEffectListener?.Invoke(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.Effect);
             //音频事件帧监听
-            if(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.AudioIndex >0 && onAudioListener!=null) onAudioListener(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.AudioIndex);
+            if (_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.AudioIndex > 0)
+                onAudioListener?.Invoke(_frames[_currentAnime.CurrentFrame].AnimeFrameInfo.AudioIndex);
             
             _currentAnime.CurrentFrame++;
         }

+ 115 - 114
CrossgateToolkit/Audio.cs

@@ -163,67 +163,67 @@ namespace CrossgateToolkit
 
         private static Dictionary<int, string> _effectMap = new Dictionary<int, string>()
         {
-            [1] = "cgnat00",
-            [2] = "cgnat01",
-            [3] = "cgnat02",
-            [4] = "cgnat03",
-            [5] = "cgnat04",
-            [6] = "cgnat05a",
-            [7] = "cgnat05b",
-            [8] = "cgnat06a",
-            [9] = "cgnat06b",
-            [10] = "cgnat07",
-            [11] = "cgnat08",
-            [12] = "cgnat09",
-            [13] = "cgnat10",
-            [14] = "cgnat11",
-            [15] = "exnat00",
-            [16] = "v2mon150a",
-            [17] = "34sand_clock",
-            [18] = "35sand_clock",
-            [19] = "36wind",
-            [20] = "37bird",
-            [21] = "puk3_Wind01",
-            [22] = "puk3_Wind02",
-            [23] = "puk3_Wind03",
-            [24] = "puk3_gaya01",
-            [25] = "puk3_drop01",
-            [26] = "puk3_drop02",
-            [51] = "cgsys00",
-            [52] = "cgsys01",
-            [53] = "cgsys02",
-            [54] = "cgsys03",
-            [55] = "cgsys04",
-            [56] = "cgsys05",
-            [57] = "cgsys06",
-            [58] = "cgsys07",
-            [59] = "cgsys08",
-            [60] = "cgsys09",
-            [61] = "cgsys10a",
-            [62] = "cgsys10b",
-            [63] = "cgsys11",
-            [64] = "cgsys12",
-            [65] = "cgsys13a",
-            [66] = "cgsys13b",
-            [67] = "cgsys13c",
-            [68] = "cgsys14",
-            [69] = "cgsys15",
-            [71] = "cgsys17",
-            [72] = "cgsys18",
-            [73] = "cgsys19",
-            [74] = "cgsys20",
-            [75] = "cgsys21",
-            [76] = "cgsys22",
-            [77] = "cgsys23",
-            [78] = "cgsys24",
-            [79] = "cgsys25",
+            [1] = "cgnat00",//环境音 流水
+            [2] = "cgnat01",//环境音 流水
+            [3] = "cgnat02",//环境音 港口船边
+            [4] = "cgnat03",//环境音 风声(火山顶那种)
+            [5] = "cgnat04",//环境音 (火山)
+            [6] = "cgnat05a",//环境音 洞穴滴水
+            [7] = "cgnat05b",//环境音 洞穴滴水
+            [8] = "cgnat06a",//环境音 草丛
+            [9] = "cgnat06b",//环境音 草丛
+            [10] = "cgnat07",//环境音 树林
+            [11] = "cgnat08",//环境音 树林
+            [12] = "cgnat09",//环境音 瀑布
+            [13] = "cgnat10",//环境音 篝火
+            [14] = "cgnat11",//环境音 火旁
+            [15] = "exnat00",//环境音 穿行驶时甲板上
+            [16] = "v2mon150a",//环境音 雷声
+            [17] = "34sand_clock",//环境音 不知道
+            [18] = "35sand_clock",//环境音 不知道
+            [19] = "36wind",//环境音 不知道
+            [20] = "37bird",//环境音 鸟叫
+            [21] = "puk3_Wind01",// 无
+            [22] = "puk3_Wind02",// 无
+            [23] = "puk3_Wind03",// 无
+            [24] = "puk3_gaya01",//无
+            [25] = "puk3_drop01",//无
+            [26] = "puk3_drop02",//无
+            [51] = "cgsys00",//鼠标左键点击
+            [52] = "cgsys01",//鼠标左键点击道具
+            [53] = "cgsys02",//点击登录
+            [54] = "cgsys03",//点击返回
+            [55] = "cgsys04",//点选不能使用的道具
+            [56] = "cgsys05",//弹窗
+            [57] = "cgsys06",//选择道具使用目标
+            [58] = "cgsys07",//翻页
+            [59] = "cgsys08",//登录角色
+            [60] = "cgsys09",//登出
+            [61] = "cgsys10a",//暗杀
+            [62] = "cgsys10b",//暗杀
+            [63] = "cgsys11",//邮件
+            [64] = "cgsys12",//宠物升级
+            [65] = "cgsys13a",//未知
+            [66] = "cgsys13b",//丢钱在地上
+            [67] = "cgsys13c",//丢钱在地上
+            [68] = "cgsys14",//捡起地上物品
+            [69] = "cgsys15",//扔地上物品
+            [71] = "cgsys17",//加入队伍
+            [72] = "cgsys18",//退出队伍
+            [73] = "cgsys19",//换名片
+            [74] = "cgsys20",//频道说话
+            [75] = "cgsys21",//未知
+            [76] = "cgsys22",//打开道具如果里面没东西
+            [77] = "cgsys23",//使用料理
+            [78] = "cgsys24",//使用道具给队友
+            [79] = "cgsys25",//使用道具给队友
             [101] = "cgply00a",
             [102] = "cgply00b",
             [103] = "cgply01a",
             [104] = "cgply01b",
             [105] = "cgply02a",
             [106] = "cgply02b",
-            [107] = "cgply03a",
+            [107] = "cgply03a",//空手MIS
             [108] = "cgply03b",
             [109] = "cgply04a",
             [110] = "cgply04b",
@@ -232,7 +232,7 @@ namespace CrossgateToolkit
             [113] = "cgply06a1",
             [114] = "cgply06b1",
             [115] = "cgply06a2",
-            [116] = "cgply06b2",
+            [116] = "cgply06b2",//冰冻5-7(冰的声音先出 然后是这个)
             [117] = "cgply07a",
             [118] = "cgply07b",
             [131] = "cgply06a2",
@@ -288,63 +288,63 @@ namespace CrossgateToolkit
             [198] = "cgmon_sample01",
             [199] = "cgmon_sample02",
             [200] = "cgmon_sample03",
-            [201] = "cgbtl00",
-            [202] = "cgbtl01",
-            [204] = "cgbtl03",
-            [205] = "cgbtl04",
-            [206] = "cgbtl05",
-            [207] = "cgbtl06",
-            [208] = "cgbtl07",
-            [209] = "cgbtl08",
-            [210] = "cgbtl09",
-            [211] = "cgbtl10",
-            [212] = "cgbtl11",
-            [213] = "cgbtl12",
-            [214] = "cgbtl13",
-            [215] = "cgbtl14",
-            [216] = "cgbtl15",
-            [217] = "cgbtl16",
-            [218] = "cgbtl17",
-            [251] = "cgefc00",
-            [252] = "cgefc01",
-            [253] = "cgefc02",
-            [254] = "cgefc03",
-            [255] = "cgefc04",
-            [256] = "cgefc05",
-            [257] = "cgefc06",
-            [258] = "cgefc07",
-            [259] = "cgefc08",
-            [260] = "cgefc09",
-            [261] = "cgefc10",
-            [262] = "cgefc11",
-            [263] = "cgefc12",
-            [264] = "cgefc13",
-            [266] = "cgefc15",
-            [267] = "cgefc16",
-            [268] = "cgefc17",
-            [269] = "cgefc18",
-            [270] = "cgefc19",
-            [271] = "cgefc20",
-            [272] = "cgefc21",
-            [273] = "cgefc22",
-            [274] = "cgefc23",
-            [275] = "cgefc24",
-            [276] = "cgefc25",
-            [277] = "cgefc26",
-            [278] = "cgefc27",
-            [279] = "cgefc28",
-            [280] = "cgefc29",
-            [281] = "cgefc30",
-            [282] = "cgefc31",
-            [283] = "cgefc32",
-            [284] = "cgefc33",
-            [285] = "cgefc34",
-            [286] = "cgefc35",
-            [287] = "cgefc36",
-            [288] = "cgefc37a",
-            [289] = "cgefc37b",
-            [290] = "cgefc37c",
-            [291] = "cgefc38",
+            [201] = "cgbtl00",//遇敌进入战斗
+            [202] = "cgbtl01",//倒数快到时
+            [204] = "cgbtl03",//召唤宠物
+            [205] = "cgbtl04",//收回宠物
+            [206] = "cgbtl05",//战斗中技能升级
+            [207] = "cgbtl06",//击飞
+            [208] = "cgbtl07",//击飞过程碰壁
+            [209] = "cgbtl08",//战斗中换武器
+            [210] = "cgbtl09",//战斗中换位置
+            [211] = "cgbtl10",//逃跑
+            [212] = "cgbtl11",//封印扔卡
+            [213] = "cgbtl12",//封印捕捉中
+            [214] = "cgbtl13",//装备击碎
+            [215] = "cgbtl14",//死亡
+            [216] = "cgbtl15",//未知
+            [217] = "cgbtl16",//使用道具前置
+            [218] = "cgbtl17",//怪物死亡气泡
+            [251] = "cgefc00",//物理技能使用前置(绿光)
+            [252] = "cgefc01",//未知
+            [253] = "cgefc02",//反击
+            [254] = "cgefc03",//气功弹飞的过程中
+            [255] = "cgefc04",//气功弹打到身上
+            [256] = "cgefc05",//明镜止水出恢复数字时
+            [257] = "cgefc06",//偷窃成功
+            [258] = "cgefc07",//偷窃失败
+            [259] = "cgefc08",//魔法施法
+            [260] = "cgefc09",//状态技能 各种吸无反施法
+            [261] = "cgefc10",//传教施法
+            [262] = "cgefc11",//陨石魔法下落
+            [263] = "cgefc12",//10级陨石打身上时
+            [264] = "cgefc13",//冰冻魔法为造成伤害的前置动画声音
+            [266] = "cgefc15",//1-4火
+            [267] = "cgefc16",//5-7火
+            [268] = "cgefc17",//1-4风
+            [269] = "cgefc18",//5-7风
+            [270] = "cgefc19",//吸血造成伤害时
+            [271] = "cgefc20",//吸血回复血量时
+            [272] = "cgefc21",//咒术怪物时气泡
+            [273] = "cgefc22",//毒咒掉血时
+            [274] = "cgefc23",//酒醉掉魔时
+            [275] = "cgefc24",//祈祷魔封动画展开时
+            [276] = "cgefc25",//属性反转
+            [277] = "cgefc26",//功无攻反等套身上时
+            [278] = "cgefc27",//补血魔法补血时
+            [279] = "cgefc28",//恢复魔法恢复时
+            [280] = "cgefc29",//气绝
+            [281] = "cgefc30",//洁净
+            [282] = "cgefc31",//10火
+            [283] = "cgefc32",//跳舞10级
+            [284] = "cgefc33",//祭死
+            [285] = "cgefc34",//未知
+            [286] = "cgefc35",//功无魔无抵挡时
+            [287] = "cgefc36",//正常反击
+            [288] = "cgefc37a",//自爆变大中
+            [289] = "cgefc37b",//自爆准备爆炸
+            [290] = "cgefc37c",//自爆爆炸
+            [291] = "cgefc38",//恢复套的过程
             [296] = "v2monex1",
             [297] = "v2monex2",
             [298] = "v2monex3",
@@ -404,8 +404,9 @@ namespace CrossgateToolkit
             [433] = "33_wind_off",
             [435] = "36wind",
             [436] = "37bird",
-            [437] = "38make_gild",
+            [437] = "38make_gild",//升级
             [438] = "39levelup",
+
         };
     }
 }

+ 3 - 0
CrossgateToolkit/Graphic.cs

@@ -39,6 +39,7 @@ namespace CrossgateToolkit
             // 解析Bin文件目录结构
             if(!Directory.Exists(CGTool.PATH.BIN)) throw new Exception("图档目录不存在,请检查CGTool中是否配置相应PATH路径");
 
+            float time = Time.realtimeSinceStartup;
             // 整理目录结构,生成对应待处理文件列表
             List<DirectoryInfo> _directorys = new List<DirectoryInfo>();
             _directorys.Add(new DirectoryInfo(CGTool.PATH.BIN));
@@ -62,6 +63,8 @@ namespace CrossgateToolkit
             {
                 Anime.Init(animeFilePair.Version, animeFilePair.InfoFile, animeFilePair.DataFile);
             }
+            
+            Debug.Log("[CGTool] 图档资源加载完毕,耗时: " + (Time.realtimeSinceStartup - time) + "s");
         }
 
         // 版本号分析