Browse Source

添加CGTool的使用示例

HonorLee 1 month ago
parent
commit
147d27d7f4
41 changed files with 8842 additions and 23 deletions
  1. 0 2
      CrossgateToolkit/Anime.cs
  2. 8 1
      CrossgateToolkit/CGTool.cs
  3. 78 8
      CrossgateToolkit/GraphicData.cs
  4. 62 12
      CrossgateToolkit/GraphicInfo.cs
  5. 8 0
      example.meta
  6. 8 0
      example/Prefeb.meta
  7. 106 0
      example/Prefeb/Prefeb_Unit.prefab
  8. 7 0
      example/Prefeb/Prefeb_Unit.prefab.meta
  9. 8 0
      example/Scene.meta
  10. 904 0
      example/Scene/1.Graphic.unity
  11. 7 0
      example/Scene/1.Graphic.unity.meta
  12. 2158 0
      example/Scene/2.Anime_SingleUnit.unity
  13. 7 0
      example/Scene/2.Anime_SingleUnit.unity.meta
  14. 1153 0
      example/Scene/3.Anime_MultiUnit.unity
  15. 7 0
      example/Scene/3.Anime_MultiUnit.unity.meta
  16. 1711 0
      example/Scene/4.Anime_UnitControl.unity
  17. 7 0
      example/Scene/4.Anime_UnitControl.unity.meta
  18. 1078 0
      example/Scene/5.Map.unity
  19. 7 0
      example/Scene/5.Map.unity.meta
  20. 8 0
      example/Script.meta
  21. 39 0
      example/Script/Prefeb_Unit.cs
  22. 11 0
      example/Script/Prefeb_Unit.cs.meta
  23. 70 0
      example/Script/Scene_Anime_MultiUnit.cs
  24. 11 0
      example/Script/Scene_Anime_MultiUnit.cs.meta
  25. 68 0
      example/Script/Scene_Anime_SingleUnit.cs
  26. 11 0
      example/Script/Scene_Anime_SingleUnit.cs.meta
  27. 123 0
      example/Script/Scene_Anime_UnitControl.cs
  28. 11 0
      example/Script/Scene_Anime_UnitControl.cs.meta
  29. 125 0
      example/Script/Scene_Graphic.cs
  30. 11 0
      example/Script/Scene_Graphic.cs.meta
  31. 202 0
      example/Script/Scene_Map.cs
  32. 11 0
      example/Script/Scene_Map.cs.meta
  33. 393 0
      example/Script/Util.cs
  34. 11 0
      example/Script/Util.cs.meta
  35. 8 0
      example/Temp.meta
  36. BIN
      example/Temp/AnimePlayerProps.jpg
  37. 135 0
      example/Temp/AnimePlayerProps.jpg.meta
  38. BIN
      example/Temp/MapTileSorting.png
  39. 135 0
      example/Temp/MapTileSorting.png.meta
  40. BIN
      example/Temp/minimap_tile.png
  41. 135 0
      example/Temp/minimap_tile.png.meta

+ 0 - 2
CrossgateToolkit/Anime.cs

@@ -329,8 +329,6 @@ namespace CrossgateToolkit
             GraphicDetail[] graphicDetails = new GraphicDetail[animeDetail.FrameCount];
             
             //合并后的Texture2D尺寸
-            uint textureWidth = 0;
-            uint textureHeight = 0;
             List<GraphicInfoData> graphicInfoDatas = new List<GraphicInfoData>();
             Dictionary<uint,GraphicInfoData> graphicInfoDataDict = new Dictionary<uint, GraphicInfoData>();
             int subPaletIndex = -1;

+ 8 - 1
CrossgateToolkit/CGTool.cs

@@ -41,20 +41,27 @@ namespace CrossgateToolkit
             BGM = Environment.CurrentDirectory + "/bgm",
             AUDIO = Environment.CurrentDirectory + "/se"
         };
+        
+        public static string ENCRYPT_KEY = "";
 
         /**
          * 初始化CGTool,并按顺序加载并初始化指定模块
          * Graphic加载顺序以Bin目录中的文件名排序
          * 其中Bin目录根目录下优先级最高,其次是Bin目录下的子目录
          */
-        public static void Init()
+        public static void Init(string encryptKey = "")
         {
+            // 加密KEY
+            ENCRYPT_KEY = encryptKey;
+            
             // 初始化调色板
             if (PATH.PAL != null) Palet.Init();
             // 初始化图档解析器
             if (PATH.BIN != null) Graphic.Init();
             // 初始化地图索引
             if (PATH.MAP != null) Map.Init();
+            
+            
             Debug.Log("[CGTool] CGTool初始化完成");
         }
 

+ 78 - 8
CrossgateToolkit/GraphicData.cs

@@ -336,14 +336,85 @@ namespace CrossgateToolkit
 
             //调整流指针
             BinaryReader fileReader = graphicInfoData.GraphicReader;
-            fileReader.BaseStream.Position = graphicInfoData.Addr;
-
-            //读入目标字节集
-            byte[] Content = fileReader.ReadBytes((int)graphicInfoData.Length);
-
-            //读取缓存字节集
-            BinaryReader contentReader = new BinaryReader(new MemoryStream(Content));
+            BinaryReader contentReader = null;
+            
+            if(graphicInfoData.IsEncrypted)
+            {
+                // 解密
+                long position = graphicInfoData.Addr + 3;
+                byte[] content;
+                // 由于秘钥被嵌入到数据流中,先检查当前位与秘钥位置和长度关系,且图档文件最开始多3个字节的头信息
+                // 1.不包含:位置+数据长度小于秘钥索引
+                if (position + graphicInfoData.Length < graphicInfoData.EncryptInfo.PwdIndex)
+                {
+                    // Debug.Log($"不包含秘钥:{graphicInfoData.Index}");
+                    // 不处理
+                    fileReader.BaseStream.Position = position;
+                    content = fileReader.ReadBytes((int)graphicInfoData.Length);
+                    
+                }else // 2.包含秘钥:位置小于秘钥索引,但是位置+数据长度大于秘钥索引,秘钥将数据分割
+                if (position < graphicInfoData.EncryptInfo.PwdIndex && // 数据索引小于秘钥索引
+                    position + graphicInfoData.Length > graphicInfoData.EncryptInfo.PwdIndex) // 数据索引+数据长度大于秘钥索引 
+                {
+                    // Debug.Log($"包含秘钥:{graphicInfoData.Index}");
+                    // 读取秘钥前数据,注意这里的长度是秘钥索引-数据索引+3
+                    int preLen = (int)(graphicInfoData.EncryptInfo.PwdIndex - position + 3);
+                    fileReader.BaseStream.Position = position;
+                    byte[] preContent = fileReader.ReadBytes(preLen);
+                    // 读取秘钥后数据
+                    int nextLen = (int)(graphicInfoData.Length - preLen);
+                    fileReader.BaseStream.Position = graphicInfoData.EncryptInfo.PwdIndex + graphicInfoData.EncryptInfo.PwdLen;
+                    byte[] nextContent = fileReader.ReadBytes(nextLen);
+                    // 合并数据
+                    content = preContent.Concat(nextContent).ToArray();
+                }
+                else // 3.秘钥之后:位置大于秘钥索引,数据位置需要加上秘钥长度
+                {
+                    // Debug.Log($"秘钥之后:{graphicInfoData.Index}");
+                    fileReader.BaseStream.Position = position + graphicInfoData.EncryptInfo.PwdLen;
+                    content = fileReader.ReadBytes((int)graphicInfoData.Length);
+                }
+                // 读取缓存字节集
+                contentReader = new BinaryReader(new MemoryStream(content));
+                
+                int pwdIndex = 0;
+                byte[] head = contentReader.ReadBytes(2);
+                // 寻找解密头数据的密码索引
+                for (int i = 0; i < graphicInfoData.EncryptInfo.Pwd.Length; i++)
+                {
+                    if((head[0]^graphicInfoData.EncryptInfo.Pwd[i]) == 0x52)
+                    {
+                        int next = i + 1;
+                        if (i == graphicInfoData.EncryptInfo.Pwd.Length - 1) next = 0;
+                        if ((head[1] ^ graphicInfoData.EncryptInfo.Pwd[next]) == 0x44)
+                        {
+                            pwdIndex = i;
+                            break;    
+                        }
+                    }
+                }
+                contentReader.Dispose();
+                
+                // 解密数据
+                for (int i = 0; i < content.Length; i++)
+                {
+                    content[i] = (byte)(content[i] ^ graphicInfoData.EncryptInfo.Pwd[pwdIndex]);
+                    pwdIndex++;
+                    if(pwdIndex >= graphicInfoData.EncryptInfo.Pwd.Length) pwdIndex = 0;
+                }
+                //读取缓存字节集
+                contentReader = new BinaryReader(new MemoryStream(content));
+            }
+            else
+            {
+                fileReader.BaseStream.Position = graphicInfoData.Addr;
+                //读入目标字节集
+                byte[] Content = fileReader.ReadBytes((int)graphicInfoData.Length);
 
+                //读取缓存字节集
+                contentReader = new BinaryReader(new MemoryStream(Content));
+            }
+            
             //16字节头信息
             byte[] RD = contentReader.ReadBytes(2);
             // 研究了几个图档数据,这个字节分别有 0~3 不同类型
@@ -359,7 +430,6 @@ namespace CrossgateToolkit
             uint DataLen = contentReader.ReadUInt32();
             uint innerPaletLen = 0;
 
-
             // 低版本头部长度为16,高版本为20
             int headLen = 16;
             if (Version > 1)

+ 62 - 12
CrossgateToolkit/GraphicInfo.cs

@@ -11,7 +11,6 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Text.RegularExpressions;
 using UnityEngine;
 
 namespace CrossgateToolkit
@@ -54,6 +53,17 @@ namespace CrossgateToolkit
         //已解压的调色板索引
         public byte[] UnpackedPaletIndex;
         public List<Color32> InnerPalet;
+
+        public bool IsEncrypted;
+        public EncryptInfo EncryptInfo;
+    }
+
+    public class EncryptInfo
+    {
+        public long PwdIndex;
+        public int PwdLen;
+        public byte[] Pwd;
+        
     }
 
     public class GraphicInfo:MonoBehaviour
@@ -73,8 +83,54 @@ namespace CrossgateToolkit
             FileStream graphicFileStream = graphicFile.OpenRead();
             BinaryReader graphicFileReader = new BinaryReader(graphicFileStream);
             
+            byte[] head = graphicFileReader.ReadBytes(3);
+            bool isEncrypted = false;
+            EncryptInfo encryptInfo = null;
+            if (head[0] == 0x52 && head[1] == 0x44) isEncrypted = false;
+            else
+            {
+                isEncrypted = true;
+                bool fromHead = head[0] % 2 == 0;
+                encryptInfo = new EncryptInfo();
+                encryptInfo.PwdLen = head[2];
+                
+                // 密码索引
+                if (fromHead)
+                {
+                    encryptInfo.PwdIndex = 3 + head[1];
+                }
+                else
+                {
+                    // 获取文件大小
+                    long fileSize = graphicFile.Length;
+                    encryptInfo.PwdIndex = fileSize - encryptInfo.PwdLen - 3 - head[1] + 3;
+                }
+
+                // 获取密码
+                graphicFileStream.Position = encryptInfo.PwdIndex;
+                encryptInfo.Pwd = graphicFileReader.ReadBytes(encryptInfo.PwdLen);
+                
+                // 密码解密
+                byte[] keyCodes = new byte[CGTool.ENCRYPT_KEY.Length];
+                for (var i = 0; i < CGTool.ENCRYPT_KEY.Length; i++)
+                {
+                    // 获取秘钥的ASCII码
+                    byte code = (byte)(CGTool.ENCRYPT_KEY[i]);
+                    keyCodes[i] = code;
+                }
+
+                // 解密密码
+                for (int i = 0; i < encryptInfo.PwdLen; i++)
+                {
+                    for (var i1 = 0; i1 < keyCodes.Length; i1++)
+                    {
+                        encryptInfo.Pwd[i] = (byte)(encryptInfo.Pwd[i] ^ keyCodes[i1]);
+
+                    }
+                }
+            }
+            
             //解析Info数据表
-            // List<GraphicInfoData> infoDatas = new List<GraphicInfoData>();
             long DataLength = fileStream.Length/40;
             for (int i = 0; i < DataLength; i++)
             {
@@ -88,19 +144,13 @@ namespace CrossgateToolkit
                 graphicInfoData.Height = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
                 graphicInfoData.East = fileReader.ReadByte();
                 graphicInfoData.South = fileReader.ReadByte();
-                byte Blocked = fileReader.ReadByte();
-                graphicInfoData.Blocked =  Blocked % 2 == 0;
+                graphicInfoData.Blocked =  fileReader.ReadByte() % 2 == 0;
                 graphicInfoData.AsGround = fileReader.ReadByte() == 1;
                 graphicInfoData.Unknow = fileReader.ReadBytes(4);
                 graphicInfoData.Serial = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
                 graphicInfoData.GraphicReader = graphicFileReader;
-                // if (graphicInfoData.Serial == 220759)
-                // {
-                //     Debug.LogError(graphicInfoData.Serial + "穿越" + Blocked);
-                //     Debug.LogError(graphicInfoData.Serial + "穿越" + graphicInfoData.Blocked);
-                //     Debug.LogError(graphicInfoData.Serial + "穿越" + graphicInfoData.Width);
-                //     Debug.LogError(graphicInfoData.Serial + "穿越" + graphicInfoData.Height);
-                // } 
+                graphicInfoData.IsEncrypted = isEncrypted;
+                graphicInfoData.EncryptInfo = encryptInfo;
                 // if (graphicInfoData.Serial >= 220000 && graphicInfoData.Width == 64 && graphicInfoData.Height == 47 && graphicInfoData.Blocked)
                 // {
                 //     Debug.LogError(graphicInfoData.Serial + "穿越" + Blocked);
@@ -127,7 +177,7 @@ namespace CrossgateToolkit
             Debug.Log("[CGTool] 加载GraphicInfo - 文件: [" +
                       // (Graphic.Flag_HighVersion[Version] ? "H" : "N") + "] [" +
                       Version + "] " +
-                      graphicInfoFile.Name + " 贴图总量: " + DataLength);
+                      graphicInfoFile.Name + " 贴图总量: " + DataLength + (isEncrypted ? " 加密图档" : ""));
         }
         
         //获取GraphicInfoData

+ 8 - 0
example.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d3c89cc2d681f4586b2b8fc1bfe480b3
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
example/Prefeb.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c291698ed7c6e4b4b82c906b9263c401
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 106 - 0
example/Prefeb/Prefeb_Unit.prefab

@@ -0,0 +1,106 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &3581443505488461264
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3581443505488461265}
+  - component: {fileID: 3581443505488461266}
+  m_Layer: 5
+  m_Name: AnimePlayer
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3581443505488461265
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3581443505488461264}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 3581443506478119344}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0}
+  m_AnchorMax: {x: 0.5, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0}
+--- !u!114 &3581443505488461266
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3581443505488461264}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: bd9d50e4c140946e284602bc0c4bea54, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  isRenderByImage: 1
+  isFrameBatch: 1
+  isLinearFilter: 0
+  frameTexture: {fileID: 0}
+--- !u!1 &3581443506478119343
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 3581443506478119344}
+  - component: {fileID: 3172618607091955258}
+  m_Layer: 5
+  m_Name: Prefeb_Unit
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &3581443506478119344
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3581443506478119343}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 3581443505488461265}
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0}
+--- !u!114 &3172618607091955258
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3581443506478119343}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9044c999cb58e4222a5047f68edd378c, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  animePlayer: {fileID: 3581443505488461266}

+ 7 - 0
example/Prefeb/Prefeb_Unit.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3ff3199d7cebb4e46b310b9943cf73b2
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
example/Scene.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 303dc18db856e4c9ea1fbe6761bd3c51
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 904 - 0
example/Scene/1.Graphic.unity

@@ -0,0 +1,904 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!29 &1
+OcclusionCullingSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 2
+  m_OcclusionBakeSettings:
+    smallestOccluder: 5
+    smallestHole: 0.25
+    backfaceThreshold: 100
+  m_SceneGUID: 00000000000000000000000000000000
+  m_OcclusionCullingData: {fileID: 0}
+--- !u!104 &2
+RenderSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 9
+  m_Fog: 0
+  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+  m_FogMode: 3
+  m_FogDensity: 0.01
+  m_LinearFogStart: 0
+  m_LinearFogEnd: 300
+  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
+  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
+  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
+  m_AmbientIntensity: 1
+  m_AmbientMode: 3
+  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
+  m_SkyboxMaterial: {fileID: 0}
+  m_HaloStrength: 0.5
+  m_FlareStrength: 1
+  m_FlareFadeSpeed: 3
+  m_HaloTexture: {fileID: 0}
+  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
+  m_DefaultReflectionMode: 0
+  m_DefaultReflectionResolution: 128
+  m_ReflectionBounces: 1
+  m_ReflectionIntensity: 1
+  m_CustomReflection: {fileID: 0}
+  m_Sun: {fileID: 0}
+  m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
+  m_UseRadianceAmbientProbe: 0
+--- !u!157 &3
+LightmapSettings:
+  m_ObjectHideFlags: 0
+  serializedVersion: 12
+  m_GIWorkflowMode: 1
+  m_GISettings:
+    serializedVersion: 2
+    m_BounceScale: 1
+    m_IndirectOutputScale: 1
+    m_AlbedoBoost: 1
+    m_EnvironmentLightingMode: 0
+    m_EnableBakedLightmaps: 0
+    m_EnableRealtimeLightmaps: 0
+  m_LightmapEditorSettings:
+    serializedVersion: 12
+    m_Resolution: 2
+    m_BakeResolution: 40
+    m_AtlasSize: 1024
+    m_AO: 0
+    m_AOMaxDistance: 1
+    m_CompAOExponent: 1
+    m_CompAOExponentDirect: 0
+    m_ExtractAmbientOcclusion: 0
+    m_Padding: 2
+    m_LightmapParameters: {fileID: 0}
+    m_LightmapsBakeMode: 1
+    m_TextureCompression: 1
+    m_FinalGather: 0
+    m_FinalGatherFiltering: 1
+    m_FinalGatherRayCount: 256
+    m_ReflectionCompression: 2
+    m_MixedBakeMode: 2
+    m_BakeBackend: 1
+    m_PVRSampling: 1
+    m_PVRDirectSampleCount: 32
+    m_PVRSampleCount: 512
+    m_PVRBounces: 2
+    m_PVREnvironmentSampleCount: 256
+    m_PVREnvironmentReferencePointCount: 2048
+    m_PVRFilteringMode: 1
+    m_PVRDenoiserTypeDirect: 1
+    m_PVRDenoiserTypeIndirect: 1
+    m_PVRDenoiserTypeAO: 1
+    m_PVRFilterTypeDirect: 0
+    m_PVRFilterTypeIndirect: 0
+    m_PVRFilterTypeAO: 0
+    m_PVREnvironmentMIS: 1
+    m_PVRCulling: 1
+    m_PVRFilteringGaussRadiusDirect: 1
+    m_PVRFilteringGaussRadiusIndirect: 5
+    m_PVRFilteringGaussRadiusAO: 2
+    m_PVRFilteringAtrousPositionSigmaDirect: 0.5
+    m_PVRFilteringAtrousPositionSigmaIndirect: 2
+    m_PVRFilteringAtrousPositionSigmaAO: 1
+    m_ExportTrainingData: 0
+    m_TrainingDataDestination: TrainingData
+    m_LightProbeSampleCountMultiplier: 4
+  m_LightingDataAsset: {fileID: 0}
+  m_LightingSettings: {fileID: 0}
+--- !u!196 &4
+NavMeshSettings:
+  serializedVersion: 2
+  m_ObjectHideFlags: 0
+  m_BuildSettings:
+    serializedVersion: 2
+    agentTypeID: 0
+    agentRadius: 0.5
+    agentHeight: 2
+    agentSlope: 45
+    agentClimb: 0.4
+    ledgeDropHeight: 0
+    maxJumpAcrossDistance: 0
+    minRegionArea: 2
+    manualCellSize: 0
+    cellSize: 0.16666667
+    manualTileSize: 0
+    tileSize: 256
+    accuratePlacement: 0
+    maxJobWorkers: 0
+    preserveTilesOutsideBounds: 0
+    debug:
+      m_Flags: 0
+  m_NavMeshData: {fileID: 0}
+--- !u!1 &100402817
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 100402818}
+  m_Layer: 5
+  m_Name: Texts
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &100402818
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 100402817}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1543025706}
+  - {fileID: 873961145}
+  - {fileID: 365276856}
+  m_Father: {fileID: 1962724930}
+  m_RootOrder: 3
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: -269}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!1 &365276855
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 365276856}
+  - component: {fileID: 365276858}
+  - component: {fileID: 365276857}
+  m_Layer: 5
+  m_Name: Dynamic
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &365276856
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 365276855}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 100402818}
+  m_RootOrder: 2
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 354, y: 0}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &365276857
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 365276855}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: "\u52A8\u6001\u56FE\u96C6"
+--- !u!222 &365276858
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 365276855}
+  m_CullTransparentMesh: 1
+--- !u!1 &697924726
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 697924729}
+  - component: {fileID: 697924728}
+  - component: {fileID: 697924727}
+  m_Layer: 0
+  m_Name: Main Camera
+  m_TagString: MainCamera
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!81 &697924727
+AudioListener:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 697924726}
+  m_Enabled: 1
+--- !u!20 &697924728
+Camera:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 697924726}
+  m_Enabled: 1
+  serializedVersion: 2
+  m_ClearFlags: 1
+  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
+  m_projectionMatrixMode: 1
+  m_GateFitMode: 2
+  m_FOVAxisMode: 0
+  m_SensorSize: {x: 36, y: 24}
+  m_LensShift: {x: 0, y: 0}
+  m_FocalLength: 50
+  m_NormalizedViewPortRect:
+    serializedVersion: 2
+    x: 0
+    y: 0
+    width: 1
+    height: 1
+  near clip plane: 0.3
+  far clip plane: 1000
+  field of view: 60
+  orthographic: 1
+  orthographic size: 5
+  m_Depth: -1
+  m_CullingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+  m_RenderingPath: -1
+  m_TargetTexture: {fileID: 0}
+  m_TargetDisplay: 0
+  m_TargetEye: 3
+  m_HDR: 1
+  m_AllowMSAA: 1
+  m_AllowDynamicResolution: 0
+  m_ForceIntoRT: 0
+  m_OcclusionCulling: 1
+  m_StereoConvergence: 10
+  m_StereoSeparation: 0.022
+--- !u!4 &697924729
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 697924726}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: -10}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &873961144
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 873961145}
+  - component: {fileID: 873961147}
+  - component: {fileID: 873961146}
+  m_Layer: 5
+  m_Name: Multi
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &873961145
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 873961144}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 100402818}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &873961146
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 873961144}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: "\u4E00\u6B21\u6027\u5408\u6279\u56FE\u96C6"
+--- !u!222 &873961147
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 873961144}
+  m_CullTransparentMesh: 1
+--- !u!1 &1233245059
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1233245060}
+  - component: {fileID: 1233245062}
+  - component: {fileID: 1233245061}
+  m_Layer: 5
+  m_Name: DynamicBatch
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1233245060
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1233245059}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1962724930}
+  m_RootOrder: 2
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 351, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1233245061
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1233245059}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1233245062
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1233245059}
+  m_CullTransparentMesh: 1
+--- !u!1 &1543025705
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1543025706}
+  - component: {fileID: 1543025708}
+  - component: {fileID: 1543025707}
+  m_Layer: 5
+  m_Name: Single
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1543025706
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1543025705}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 100402818}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: -363, y: 0}
+  m_SizeDelta: {x: 160, y: 30}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1543025707
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1543025705}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_FontData:
+    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+    m_FontSize: 16
+    m_FontStyle: 0
+    m_BestFit: 0
+    m_MinSize: 10
+    m_MaxSize: 40
+    m_Alignment: 1
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 0
+    m_VerticalOverflow: 0
+    m_LineSpacing: 1
+  m_Text: "\u5355\u4E2A\u56FE\u6863\u56FE\u50CF"
+--- !u!222 &1543025708
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1543025705}
+  m_CullTransparentMesh: 1
+--- !u!1 &1647070179
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1647070180}
+  - component: {fileID: 1647070182}
+  - component: {fileID: 1647070181}
+  m_Layer: 5
+  m_Name: SingleOne
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1647070180
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1647070179}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1962724930}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: -364, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1647070181
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1647070179}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1647070182
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1647070179}
+  m_CullTransparentMesh: 1
+--- !u!1 &1725551206
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1725551209}
+  - component: {fileID: 1725551208}
+  - component: {fileID: 1725551207}
+  m_Layer: 0
+  m_Name: EventSystem
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1725551207
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1725551206}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_SendPointerHoverToParent: 1
+  m_HorizontalAxis: Horizontal
+  m_VerticalAxis: Vertical
+  m_SubmitButton: Submit
+  m_CancelButton: Cancel
+  m_InputActionsPerSecond: 10
+  m_RepeatDelay: 0.5
+  m_ForceModuleActive: 0
+--- !u!114 &1725551208
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1725551206}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_FirstSelected: {fileID: 0}
+  m_sendNavigationEvents: 1
+  m_DragThreshold: 10
+--- !u!4 &1725551209
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1725551206}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 2
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1850437480
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1850437481}
+  - component: {fileID: 1850437483}
+  - component: {fileID: 1850437482}
+  m_Layer: 5
+  m_Name: MultiBatch
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &1850437481
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1850437480}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 1962724930}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0.5, y: 0.5}
+  m_AnchorMax: {x: 0.5, y: 0.5}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 100, y: 100}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1850437482
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1850437480}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 0}
+  m_Type: 0
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!222 &1850437483
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1850437480}
+  m_CullTransparentMesh: 1
+--- !u!1 &1962724926
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1962724930}
+  - component: {fileID: 1962724929}
+  - component: {fileID: 1962724928}
+  - component: {fileID: 1962724927}
+  - component: {fileID: 1962724931}
+  m_Layer: 5
+  m_Name: Canvas_PPU_100
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!114 &1962724927
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1962724926}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_IgnoreReversedGraphics: 1
+  m_BlockingObjects: 0
+  m_BlockingMask:
+    serializedVersion: 2
+    m_Bits: 4294967295
+--- !u!114 &1962724928
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1962724926}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_UiScaleMode: 0
+  m_ReferencePixelsPerUnit: 100
+  m_ScaleFactor: 1
+  m_ReferenceResolution: {x: 800, y: 600}
+  m_ScreenMatchMode: 0
+  m_MatchWidthOrHeight: 0
+  m_PhysicalUnit: 3
+  m_FallbackScreenDPI: 96
+  m_DefaultSpriteDPI: 96
+  m_DynamicPixelsPerUnit: 1
+  m_PresetInfoIsWorld: 0
+--- !u!223 &1962724929
+Canvas:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1962724926}
+  m_Enabled: 1
+  serializedVersion: 3
+  m_RenderMode: 0
+  m_Camera: {fileID: 0}
+  m_PlaneDistance: 100
+  m_PixelPerfect: 0
+  m_ReceivesEvents: 1
+  m_OverrideSorting: 0
+  m_OverridePixelPerfect: 0
+  m_SortingBucketNormalizedSize: 0
+  m_AdditionalShaderChannelsFlag: 0
+  m_SortingLayerID: 0
+  m_SortingOrder: 0
+  m_TargetDisplay: 0
+--- !u!224 &1962724930
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1962724926}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 0, y: 0, z: 0}
+  m_ConstrainProportionsScale: 0
+  m_Children:
+  - {fileID: 1647070180}
+  - {fileID: 1850437481}
+  - {fileID: 1233245060}
+  - {fileID: 100402818}
+  m_Father: {fileID: 0}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0}
+--- !u!114 &1962724931
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1962724926}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f0a92356c01504a1fb55daae6962c99c, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  SingleGraphic: {fileID: 1647070181}
+  BatchGraphic: {fileID: 1850437482}
+  DynamicBatchGraphic: {fileID: 1233245061}

+ 7 - 0
example/Scene/1.Graphic.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: dcd7aa09311b64ad5bb5a56cccc8deb0
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

File diff suppressed because it is too large
+ 2158 - 0
example/Scene/2.Anime_SingleUnit.unity


+ 7 - 0
example/Scene/2.Anime_SingleUnit.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1223d000f936b4360a7307947bfbc055
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

File diff suppressed because it is too large
+ 1153 - 0
example/Scene/3.Anime_MultiUnit.unity


+ 7 - 0
example/Scene/3.Anime_MultiUnit.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4a10bf8f768da4be2be1cca1e67f96b8
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

File diff suppressed because it is too large
+ 1711 - 0
example/Scene/4.Anime_UnitControl.unity


+ 7 - 0
example/Scene/4.Anime_UnitControl.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 5012f8680d8c445a98cc5913a0ca8c3b
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

File diff suppressed because it is too large
+ 1078 - 0
example/Scene/5.Map.unity


+ 7 - 0
example/Scene/5.Map.unity.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 6d1be16073a9342ccb88fd6840870bc3
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
example/Script.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3a9fec28ee385442a9f5b79c888e8bcc
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 39 - 0
example/Script/Prefeb_Unit.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+
+public class Prefeb_Unit : MonoBehaviour
+{
+    public AnimePlayer animePlayer;
+
+    public RectTransform RectTransform;
+
+    private void Awake()
+    {
+        RectTransform = GetComponent<RectTransform>();
+        // 可以监听动画播放帧中的音频事件并播放音效
+        animePlayer.onAudioListener = (audioID) =>
+        {
+            // 播放音效
+            // 1.获取AudioClip并自行交给AudioSource播放,推荐背景音乐等长时间循环音频交给AudioSource播放
+            // AudioClip audioClip = CrossgateToolkit.Audio.Play([Your AudioSource],Audio.Type.BGM,audioID);
+            
+            // 2.直接播放音效,推荐技能、人物等一次性特效音频直接交给Audio类播放和管控,即不指定AudioSource
+            CrossgateToolkit.Audio.Play(null,Audio.Type.EFFECT,audioID);
+        };
+    }
+
+    // Start is called before the first frame update
+    void Start()
+    {
+        
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        
+    }
+}

+ 11 - 0
example/Script/Prefeb_Unit.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9044c999cb58e4222a5047f68edd378c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 70 - 0
example/Script/Scene_Anime_MultiUnit.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+using Random = UnityEngine.Random;
+
+public class Scene_MultiUnit : MonoBehaviour
+{
+    public Transform UnitContainer;
+    public Prefeb_Unit unitPrefeb;
+    List<Prefeb_Unit> units = new List<Prefeb_Unit>();
+
+    private void Awake()
+    {
+        Util.Init();
+    }
+
+    void Start()
+    {
+        int x = 18;
+        int y = 5;
+        int width = x * 60;
+        int height = y * 100;
+        for (int i = 0; i < x; i++)
+        {
+            for (int j = 0; j < y; j++) 
+            {
+                Prefeb_Unit unit = Instantiate(unitPrefeb, UnitContainer);
+                unit.name = "Unit_" + i + "_" + j;
+                unit.RectTransform.anchoredPosition =
+                    new Vector2(-width / 2f + i * 60, -height / 2f + j * 100 + 10);
+                unit.animePlayer.Serial = Util.GetRandomSerial();
+                unit.animePlayer.DirectionType = Util.GetRandomDirection();
+                unit.animePlayer.ActionType = (Anime.ActionType)Random.Range(0, 21);
+                units.Add(unit);
+            }
+        }
+    }
+    
+    public void ChangeSerial()
+    {
+        foreach (var unit in units)
+        {
+            unit.animePlayer.Serial = Util.GetRandomSerial();
+        }
+    }
+    
+    public void ChangeDirection()
+    {
+        foreach (var unit in units)
+        {
+            unit.animePlayer.DirectionType = Util.GetRandomDirection();
+        }
+    }
+    
+    public void ChangeAction()
+    {
+        foreach (var unit in units)
+        {
+            unit.animePlayer.ActionType = (Anime.ActionType)Random.Range(0, 21);
+        }
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        
+    }
+}

+ 11 - 0
example/Script/Scene_Anime_MultiUnit.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 74f3c7cd98e34483b821102279c9dde0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 68 - 0
example/Script/Scene_Anime_SingleUnit.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Scene_SingleUnit : MonoBehaviour
+{
+    public AnimePlayer animePlayer;
+
+    public Anime.DirectionType DirectionType;
+    
+    public Anime.ActionType ActionType;
+
+    public uint Serial;
+
+    public Text[] Texts;
+    // Start is called before the first frame update
+    private void Awake()
+    {
+        Util.Init();
+        Serial = Util.GetRandomSerial();
+        DirectionType = Anime.DirectionType.SouthWest;
+        ActionType = Anime.ActionType.Idle;
+    }
+
+    void Start()
+    {
+        animePlayer.play(Serial,DirectionType,ActionType,Anime.PlayType.Loop);
+        UpdateText();
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        
+    }
+
+    public void ChangeUint()
+    {
+        Serial = Util.GetRandomSerial();
+        animePlayer.Serial = Serial;
+        UpdateText();
+    }
+
+    public void ChangeDirection()
+    {
+        DirectionType = Util.GetNextDirection(DirectionType);
+        animePlayer.DirectionType = DirectionType;
+        UpdateText();
+    }
+
+    public void ChangeAction()
+    {
+        // 注意不是所有角色都有 BeforeRun/AfterRun 或其他动作
+        ActionType = Util.GetNextAction(ActionType);
+        animePlayer.ActionType = ActionType;
+        UpdateText();
+    }
+
+    public void UpdateText()
+    {
+        Texts[0].text = Serial.ToString();
+        Texts[1].text = DirectionType.ToString();
+        Texts[2].text = ActionType.ToString();
+    }
+}

+ 11 - 0
example/Script/Scene_Anime_SingleUnit.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d50882c95cfdf43b58eebfcd4ff6bf37
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 123 - 0
example/Script/Scene_Anime_UnitControl.cs

@@ -0,0 +1,123 @@
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+
+public class Scene_UnitControl : MonoBehaviour
+{
+    [Header("单位列表")]
+    [Header("跑步单位")] public Prefeb_Unit Unit_Runner;
+    [Header("攻击单位")] public Prefeb_Unit Unit_Attacker;
+    [Header("防御单位")] public Prefeb_Unit Unit_Defender;
+    [Header("特效单位")] public Prefeb_Unit Unit_Effect;
+    [Header("动作单位")] public Prefeb_Unit Unit_Action;
+    // Start is called before the first frame update
+    void Start()
+    {
+        
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        
+    }
+
+    private void Awake()
+    {
+        Util.Init();
+    }
+
+    public void Play()
+    {
+        RunnerRun();
+        AttackerRun();
+        StartCoroutine(PlayControl());
+    }
+
+    private void RunnerRun()
+    {
+        // 动画队列一般用于对动画流程没有严格要求的场景
+        // 动画播放过程中,如果某个动画数据缺失或不存在,则会自动跳过该动画并自动播放下一动画
+        // 如果需要控制动画的具体播放时机和顺序或控制其他变量行为,建议使用动画回调监听方式处理
+        
+        // 以队列方式播放特殊三段式跑步动画
+        Unit_Runner.animePlayer.Serial = 105000;
+        Unit_Runner.animePlayer.DirectionType = Anime.DirectionType.South;
+        Unit_Runner.animePlayer.playOnce(Unit_Runner.animePlayer.DirectionType,Anime.ActionType.BeforeRun)
+            .nextPlay(Unit_Runner.animePlayer.DirectionType,Anime.ActionType.Run,Anime.PlayType.Once)
+            .nextPlay(Unit_Runner.animePlayer.DirectionType,Anime.ActionType.AfterRun,Anime.PlayType.Once)
+            .nextPlay(Unit_Runner.animePlayer.DirectionType,Anime.ActionType.Idle,Anime.PlayType.Loop);
+    }
+
+    private void AttackerRun()
+    {
+        // 动画帧事件监听
+        // 普通的攻击动画正常会有击中和攻击完成两种事件回调
+        // 如:小石像怪,有多段击中效果,最后一段击中则为攻击完成
+        // 又如:冰冻魔法,有多段击中效果,最后一段击中则为攻击完成
+        
+        // 但可以肯定有部分动画因图档版本问题或打包过程中出现动作帧缺失的情况,则有可能无法触发击中或是攻击完成事件
+        // 这时可能需要通过使用动画播放完成事件回调来处理
+
+        Unit_Attacker.animePlayer.Serial = 101200;
+        Unit_Attacker.animePlayer.DirectionType = Anime.DirectionType.SouthEast;
+        
+        Unit_Defender.animePlayer.Serial = 105052;
+        Unit_Defender.animePlayer.DirectionType = Anime.DirectionType.NorthWest;
+
+        Unit_Attacker.animePlayer.playOnce(Unit_Attacker.animePlayer.DirectionType, Anime.ActionType.Attack, 1f, 
+            (effectType) =>
+            {
+                // 动画事件回调
+                
+                // 击中或攻击结束效果时,出现被击中动画
+                // Unit_Effect.animePlayer.Serial = 110001;
+                Unit_Effect.animePlayer.play(110001,Anime.DirectionType.North,Anime.ActionType.Idle,Anime.PlayType.OnceAndDestroy);
+                Unit_Effect.RectTransform.position = Unit_Defender.RectTransform.position + new Vector3(0, 0.5f, 0);
+                
+                // 击中效果
+                if (effectType == Anime.EffectType.Hit)
+                {
+                    // 对于多段攻击可以延迟下一帧的帧率以达到子弹时间或是其他效果
+                    Unit_Attacker.animePlayer.DelayPlay(0.5f);
+                    // 可以在击中效果中处理受击方的受击动画效果,同样也可以控制帧率速度倍率
+                    Unit_Defender.animePlayer.playOnce(Unit_Defender.animePlayer.DirectionType, Anime.ActionType.Hurt,
+                        0.2f);
+                    // 可以给受击方增加抖动处理等等,这里不再做演示
+                }
+
+                // 攻击完成
+                if (effectType == Anime.EffectType.HitOver)
+                {
+                    // 攻击结束阶段可以处理实际的伤害数值显示等
+                    Unit_Defender.animePlayer.playOnce(Unit_Defender.animePlayer.DirectionType, Anime.ActionType.Hurt);
+                }
+            }, (act) =>
+            {
+                // 动画播放完成回调
+                // 此处可以处理动画播放完成后的逻辑处理
+                Unit_Attacker.animePlayer.ActionType = Anime.ActionType.Idle;
+            });
+    }
+
+    IEnumerator PlayControl()
+    {
+        // 通过协程以及动画播放完成监听的方式控制动画播放
+        // 也可通过非协程的多级回调方式控制动画播放,看具体应用场景和编码习惯
+        bool runAble = false;
+        Unit_Action.animePlayer.Serial = 106270;
+        Unit_Action.animePlayer.DirectionType = Anime.DirectionType.SouthWest;
+        Unit_Action.animePlayer.playOnce(Anime.DirectionType.SouthWest, Anime.ActionType.Rock, 1f, null,
+            (act) => runAble = true);
+        yield return new WaitUntil(() => runAble);
+        yield return new WaitForSeconds(0.5f);
+        runAble = false;
+        Unit_Action.animePlayer.playOnce(Anime.DirectionType.SouthWest, Anime.ActionType.Scissors, 1f, null,
+            (act) => runAble = true);
+        yield return new WaitUntil(() => runAble);
+        yield return new WaitForSeconds(0.5f);
+        Unit_Action.animePlayer.playOnce(Anime.DirectionType.SouthWest, Anime.ActionType.Paper, 1f, null,
+            (act) => runAble = true);
+    }
+}

+ 11 - 0
example/Script/Scene_Anime_UnitControl.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a9c6e5c81fd994b5db7e3ae87b874be5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 125 - 0
example/Script/Scene_Graphic.cs

@@ -0,0 +1,125 @@
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class Scene_Graphic : MonoBehaviour
+{
+    [SerializeField,Header("单张图档")]
+    private Image SingleGraphic;
+    [SerializeField,Header("合批图档")]
+    private Image BatchGraphic;
+    [SerializeField,Header("动态合批图档")]
+    private Image DynamicBatchGraphic;
+    // Start is called before the first frame update
+    void Start()
+    {
+        
+    }
+
+    // Update is called once per frame
+    void Update()
+    {
+        
+    }
+    
+    private void Awake()
+    {
+        Util.Init();
+        GetSingleGraphic();
+        
+        // 两种合批方式
+        // 可以观察两种合批方式所形成的图像图集差异
+        GetBatchGraphic();  // 一次性合批图像
+        StartCoroutine(GetDynamicBatchGraphic());  // 动态合批图像
+    }
+    
+    public void GetSingleGraphic()
+    {
+        // 获取单张图档
+        GraphicDetail graphicDetail = CrossgateToolkit.Graphic.GetGraphicDetail(10302);
+        SingleGraphic.sprite = graphicDetail.SpritePPU100;
+        SingleGraphic.SetNativeSize();
+        // 获取单张图档的PPU-100的图像
+        // SingleGraphic.sprite = CrossgateToolkit.Graphic.GetGraphicDetail(4116).SpritePPU100;
+    }
+    
+    public void GetBatchGraphic()
+    {
+        // 以合批方式获取并处理图像图集
+        // 此处使用图档编号(非索引)获取图像
+        uint[] serials = new uint[]
+        {
+            // 地面
+            4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,
+            // 其他不同尺寸图像
+            10561,10571,10573,10443,10403
+        };
+        
+        // 获取合批图集前,需要手动获取整理图像信息数据
+        List<GraphicInfoData> graphicInfoDatas = new List<GraphicInfoData>();
+        for (int i = 0; i < serials.Length; i++)
+        {
+            graphicInfoDatas.Add(CrossgateToolkit.GraphicInfo.GetGraphicInfoData(serials[i]));
+        }
+
+        // 合批图像,并获取对应编号与图像映射
+        Dictionary<uint,GraphicDetail> graphicDetails = GraphicData.BakeGraphics(graphicInfoDatas, true, 0, -1, false, 256, 5);
+        
+        // 获取合批的原图像
+        Texture2D texture2D = graphicDetails[4116].SpritePPU100.texture;
+        BatchGraphic.sprite = Sprite.Create(texture2D,new Rect(0,0,texture2D.width,texture2D.height),new Vector2(0.5f,0.5f));
+        BatchGraphic.SetNativeSize();
+        // 说明:合批图集定义最大图集尺寸为512,合批后的图像图集,尺寸不会超过512
+        // 一次性合批的图像会根据图像尺寸由小到大,由低到高方式进行排列处理,直到达到最大尺寸限制
+    }
+    
+    IEnumerator GetDynamicBatchGraphic()
+    {
+        // 以动态图集方式获取并处理图像图集
+        // 此处使用图档编号(非索引)获取图像
+        uint[] serials = new uint[]
+        {
+            // 地面
+            4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,
+            // 其他不同尺寸图像
+            10561,10571,10573,10443,10403
+        };
+        
+        // 动态图集无需手动获取整理图像信息数据
+        
+        // 首先定义图集
+        DynamicGraphic dynamicGraphic = new DynamicGraphic(256,256,5,0,false,true);
+        // 动态图集为自动动态扩容图集
+        // 当当前图集内无空余空间容纳当前填充图形时,会自动进行扩容,形成新的图集图像,但尺寸不会超过定义的图集尺寸
+
+        // 可以直接通过图像编号填充图集并获取填充后的图像数据
+        Sprite sprite = dynamicGraphic.GetSprite(4116);
+        sprite = dynamicGraphic.GetSprite(4117);
+        
+        // 可以手动清除图集避免内存泄漏
+        dynamicGraphic.Clear();
+        
+        // 亦可通过协程方式填充图集,避免大批量获取图像时造成主线程卡顿
+        // 协程方式填充图集需要通过回调方式获取填充后的图像数据
+        bool next = false;
+        for (var i = 0; i < serials.Length; i++)
+        {
+            StartCoroutine(
+                dynamicGraphic.GetSpriteSync(serials[i], (outputSprite) =>
+                {
+                    // 获取到图像数据后的处理
+                    // 此处可以将图像数据赋值给Image等UI组件
+                    // 也可以将图像数据保存到本地等
+                    sprite = outputSprite;
+                    next = true;
+                }));
+            yield return new WaitUntil(() => next);
+        }
+        
+        Texture2D texture2D = sprite.texture;
+        DynamicBatchGraphic.sprite = Sprite.Create(texture2D,new Rect(0,0,texture2D.width,texture2D.height),new Vector2(0.5f,0.5f));
+        DynamicBatchGraphic.SetNativeSize();
+    }
+}

+ 11 - 0
example/Script/Scene_Graphic.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f0a92356c01504a1fb55daae6962c99c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 202 - 0
example/Script/Scene_Map.cs

@@ -0,0 +1,202 @@
+using System.Collections;
+using System.Collections.Generic;
+using CrossgateToolkit;
+using UnityEngine;
+using UnityEngine.Tilemaps;
+
+public class Scene_Map : MonoBehaviour
+{
+    [SerializeField,Header("地图渲染用Camera")]
+    private Camera MapCamera;
+    [SerializeField,Header("地图地面TileMap")]
+    private Tilemap TileMap_Ground;
+    [SerializeField,Header("地图物件TileMap")]
+    private Tilemap TileMap_Object;
+    
+    [SerializeField,Header("地图Grid")]
+    private Grid MapGrid;
+
+    [SerializeField, Header("地图背景音乐")]
+    private AudioSource MapBGM;
+    
+    
+    [SerializeField,Header("小地图TileMap")]
+    private Tilemap TileMap_MiniMap;
+    [SerializeField,Header("小地图TileSprite")]
+    private Sprite MiniMapSprite;
+    
+    // 地图数据
+    private MapInfo mapInfo;
+    // 地图音乐
+    private uint mapBGMID;
+    // 地图图像数据
+    private Dictionary<uint,GraphicDetail> GroundGraphicDetails;
+    private Dictionary<uint,GraphicDetail> ObjectGraphicDetails;
+    
+    // Start is called before the first frame update
+    void Start()
+    {
+        // 地图渲染相机需要注意调整排序方式
+        MapCamera.transparencySortMode = TransparencySortMode.CustomAxis;
+        MapCamera.transparencySortAxis = new Vector3(0, 1, -0.1f);
+        
+        LoadMap();
+    }
+
+    private void Awake()
+    {
+        Util.Init();
+    }
+
+    private void LoadMap()
+    {
+        // 获取地图信息,此处以编号为1000的法兰城地图为例
+        mapInfo = Map.GetMap(1000);
+        
+        // 地图的数据已经过重新排序处理,无论加载的是服务端地图或是客户端地图,均按照场景中所示排序规则进行处理
+        
+        // 图集合批处理
+        BakeMapGraphics();
+        
+        // 绘制地图,此处直接绘制全图
+        // 实际使用中推荐以卡马克卷轴算法进行局部绘制,以提高性能
+        DrawMapGround();
+        DrawMapObject();
+        
+        // 调整位置
+        int x = mapInfo.Width / 2 * 32 - mapInfo.Height / 2 * 32;
+        int y = -mapInfo.Height / 2 * 24 - mapInfo.Width / 2 * 24;
+        MapGrid.GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);
+        
+        // 绘制小地图
+        DrawMiniMap();
+    }
+
+    // 对地图图像进行合批处理
+    private void BakeMapGraphics()
+    {
+        // 以合批图集的形式缓存地图图像数据
+        // 此处仅以一次性合批图集方式进行示范
+        // 如若针对服务端动态地图方式,则需要动态合批图集,可参考Scene_Graphic.cs中的GetDynamicBatchGraphic()方法进行处理
+        
+        List<GraphicInfoData> graphicInfoDatas;
+        // 获取地面数据并进行合批
+        graphicInfoDatas = new List<GraphicInfoData>();
+        for (var i = 0; i < mapInfo.GroundDatas.Count; i++)
+        {
+            MapBlockData mapBlockData = mapInfo.GroundDatas[i];
+            if(mapBlockData==null || mapBlockData.GraphicInfo==null) continue;
+            graphicInfoDatas.Add(mapBlockData.GraphicInfo);
+        }
+        GroundGraphicDetails = GraphicData.BakeGraphics(graphicInfoDatas, true, 0, -1, false, 2048);
+        
+        // 获取物件数据并进行合批
+        graphicInfoDatas = new List<GraphicInfoData>();
+        for (var i = 0; i < mapInfo.ObjectDatas.Count; i++)
+        {
+            MapBlockData mapBlockData = mapInfo.ObjectDatas[i];
+            if(mapBlockData==null || mapBlockData.GraphicInfo==null) continue;
+            graphicInfoDatas.Add(mapBlockData.GraphicInfo);
+        }
+        ObjectGraphicDetails = GraphicData.BakeGraphics(graphicInfoDatas, true, 0, -1, false, 2048);
+    }
+
+    // 绘制地图地面
+    private void DrawMapGround()
+    {
+        int width = mapInfo.Width;
+        int height = mapInfo.Height;
+        List<Vector3Int> drawPositions = new List<Vector3Int>();
+        List<Tile> drawTiles = new List<Tile>();
+        for(int x = 0; x < width; x++)
+        {
+            for(int y = 0; y < height; y++)
+            {
+                MapBlockData mapBlockData = mapInfo.GroundDatas[y * width + x];
+                if(mapBlockData==null || mapBlockData.GraphicInfo==null) continue;
+                GraphicDetail graphicDetail = GroundGraphicDetails[mapBlockData.MapSerial];
+                Tile groundTile = Tile.CreateInstance(typeof(Tile)) as Tile;
+                groundTile.sprite = graphicDetail.Sprite;
+                drawPositions.Add(new Vector3Int(x, y, 0));
+                drawTiles.Add(groundTile);
+            }
+        }
+        
+        TileMap_Ground.SetTiles(drawPositions.ToArray(), drawTiles.ToArray());
+    }
+    
+    // 绘制地图物件
+    private void DrawMapObject()
+    {
+        int width = mapInfo.Width;
+        int height = mapInfo.Height;
+        List<Vector3Int> drawPositions = new List<Vector3Int>();
+        List<Tile> drawTiles = new List<Tile>();
+        for(int x = 0; x < width; x++)
+        {
+            for(int y = 0; y < height; y++)
+            {
+                MapBlockData mapBlockData = mapInfo.ObjectDatas[y * width + x];
+                if(mapBlockData==null || mapBlockData.GraphicInfo==null) continue;
+                if (mapBlockData.GraphicInfo.Serial < 1000)
+                {
+                    // 小于1000的编号为音频编号
+                    if (mapBGMID == 0)
+                    {
+                        mapBGMID = mapBlockData.MapSerial;
+                        // 播放背景音乐
+                        Audio.Play(MapBGM, Audio.Type.BGM, (int)mapBGMID);
+                    }
+                }
+                GraphicDetail graphicDetail = ObjectGraphicDetails[mapBlockData.MapSerial];
+                Tile objectTile = Tile.CreateInstance(typeof(Tile)) as Tile;
+                objectTile.sprite = graphicDetail.Sprite;
+                // 注意排序的修正,mapBlockData提供了基础的Z轴修正,如需更精确的效果请自行计算处理
+                drawPositions.Add(new Vector3Int(x, y, 0));
+                drawTiles.Add(objectTile);
+            }
+        }
+        
+        TileMap_Object.SetTiles(drawPositions.ToArray(), drawTiles.ToArray());
+    }
+    
+    // 绘制小地图
+    private void DrawMiniMap()
+    {
+        // CGTool提供了简单的处理方式
+        // 可以直接通过获取图档数据的主色调来处理小地图
+        
+        List<Vector3Int> drawPositions = new List<Vector3Int>();
+        List<Tile> drawTiles = new List<Tile>();
+        
+        for(int x = 0; x < mapInfo.Width; x++)
+        {
+            for(int y = 0; y < mapInfo.Height; y++)
+            {
+                MapBlockData mapBlockData = mapInfo.GroundDatas[y * mapInfo.Width + x];
+                MapBlockData mapObjectData = mapInfo.ObjectDatas[y * mapInfo.Width + x];
+                if(mapBlockData==null && mapObjectData==null) continue;
+
+                Tile tile = Tile.CreateInstance(typeof(Tile)) as Tile;
+                tile.sprite = MiniMapSprite;
+                
+                
+                if (mapObjectData == null)
+                {
+                    // 没有地面物件时使用地面主色
+                    tile.color = GroundGraphicDetails[mapBlockData.MapSerial].PrimaryColor;
+                }
+                else
+                {
+                    // 有地面物件时使用物件主色,此处只做演示,正常情况下需要根据建筑物的占地尺寸对相应区块进行填充以提高小地图的视觉效果
+                    tile.color = ObjectGraphicDetails[mapObjectData.MapSerial].PrimaryColor;
+                }
+                
+                drawPositions.Add(new Vector3Int(x, y, 0));
+                drawTiles.Add(tile);
+            }
+        }
+        
+        TileMap_MiniMap.SetTiles(drawPositions.ToArray(), drawTiles.ToArray());
+    }
+}

+ 11 - 0
example/Script/Scene_Map.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a38b61199c1e24950aed7c72a8cfeaa7
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 393 - 0
example/Script/Util.cs

@@ -0,0 +1,393 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using CrossgateToolkit;
+
+public class Util
+
+{
+    public static void Init()
+    {
+        Application.targetFrameRate = 60;
+        CGTool.PATH = new CGTool.CGPath()
+        {
+            BIN = Application.persistentDataPath + "/bin",
+            PAL = Application.persistentDataPath + "/pal",
+            MAP = Application.persistentDataPath + "/map",
+            BGM = Application.persistentDataPath + "/bgm",
+            AUDIO = Application.persistentDataPath + "/se"
+        };
+        CGTool.Init();
+    }
+    // 获取距离目标单位直线方向一定距离的位置
+    public static Vector2 GetTargetNearPosition(Vector2 fromPosition,Vector2 targetPosition,float distance)
+    {
+        Vector2 direction = targetPosition - fromPosition;
+        Vector2 normalizedDirection = direction.normalized;
+
+        // Vector2 point = targetPosition - normalizedDirection * distance;
+
+        // 移动 C 点到圆上,使得 C 到 A 的距离等于半径 X
+        // float distanceToMove = Vector2.Distance(point, fromPosition) - distance;
+        Vector2 adjustedC = targetPosition - normalizedDirection * distance;
+
+        return adjustedC;
+    }
+    
+    //获取方向增量
+    public static Vector2Int GetDirectionVector(Anime.DirectionType direction)
+    {
+        Vector2Int vector2 = Vector2Int.zero;
+        switch (direction)
+        {
+            case Anime.DirectionType.North:
+                vector2.x = -1;
+                vector2.y = 1;
+                break;
+            case Anime.DirectionType.NorthEast:
+                vector2.x = 0;
+                vector2.y = 1;
+                break;
+            case Anime.DirectionType.East:
+                vector2.x = 1;
+                vector2.y = 1;
+                break;
+            case Anime.DirectionType.SouthEast:
+                vector2.x = 1;
+                vector2.y = 0;
+                break;
+            case Anime.DirectionType.South:
+                vector2.x = 1;
+                vector2.y = -1;
+                break;
+            case Anime.DirectionType.SouthWest:
+                vector2.x = 0;
+                vector2.y = -1;
+                break;
+            case Anime.DirectionType.West:
+                vector2.x = -1;
+                vector2.y = -1;
+                break;
+            case Anime.DirectionType.NorthWest:
+                vector2.x = -1;
+                vector2.y = 0;
+                break;
+        }
+
+        return vector2;
+    }
+    
+    // 获取方向上某距离的点
+    public static Vector2 GetDirectionPoint(Vector2 fromPosition,Anime.DirectionType directionType,float distance)
+    {
+        Vector2 vector2 = GetDirectionVector(directionType);
+        vector2 = vector2.normalized;
+        Vector2 point = fromPosition + vector2 * distance;
+        return point;
+    }
+    
+    // 获取目标单位方向角度
+    public static float GetTargetAngle(Vector2 fromPosition,Vector2 targetPosition)
+    {
+        Vector2 diff = targetPosition - fromPosition;
+        float angle = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
+        angle = angle - 90;
+        return angle;
+    }
+    
+    // 获取目标单位方向
+    public static Anime.DirectionType GetTargetDirection(Vector2 fromPosition,Vector2 targetPosition)
+    {
+        Vector2 diff = targetPosition - fromPosition;
+        float angle = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
+        angle = angle - 90;
+            
+        if (angle <= 25 && angle > -25) return Anime.DirectionType.NorthEast;
+        if (angle <= -25 && angle > -75) return Anime.DirectionType.East;
+        if (angle <= -75 && angle > -105) return Anime.DirectionType.SouthEast;
+        if (angle <= -105 && angle > -155) return Anime.DirectionType.South;
+        if (angle <= -155 && angle > -205) return Anime.DirectionType.SouthWest;
+        if (angle <= -205 && angle > -255) return Anime.DirectionType.West;
+        if (angle <= -255 && angle > -285) return Anime.DirectionType.NorthWest;
+        if (angle <= -285 && angle > -335) return Anime.DirectionType.North;
+        if (angle <= -335 && angle > -385) return Anime.DirectionType.NorthEast;
+            
+        if (angle > 25 && angle < 75) return Anime.DirectionType.North;
+        if (angle > 75 && angle < 105) return Anime.DirectionType.NorthWest;
+        if (angle > 105 && angle < 155) return Anime.DirectionType.West;
+        if (angle > 155 && angle < 205) return Anime.DirectionType.SouthWest;
+        if (angle > 205 && angle < 255) return Anime.DirectionType.South;
+        if (angle > 255 && angle < 285) return Anime.DirectionType.SouthEast;
+        if (angle > 285 && angle < 335) return Anime.DirectionType.East;
+        if (angle > 335 && angle < 385) return Anime.DirectionType.NorthEast;
+            
+        return Anime.DirectionType.East;
+    }
+    
+    // 获取反方向
+    public static Anime.DirectionType GetReverseDirection(Anime.DirectionType directionType)
+    {
+        switch (directionType)
+        {
+            case Anime.DirectionType.North:
+                return Anime.DirectionType.South;
+            case Anime.DirectionType.NorthEast:
+                return Anime.DirectionType.SouthWest;
+            case Anime.DirectionType.East:
+                return Anime.DirectionType.West;
+            case Anime.DirectionType.SouthEast:
+                return Anime.DirectionType.NorthWest;
+            case Anime.DirectionType.South:
+                return Anime.DirectionType.North;
+            case Anime.DirectionType.SouthWest:
+                return Anime.DirectionType.NorthEast;
+            case Anime.DirectionType.West:
+                return Anime.DirectionType.East;
+            case Anime.DirectionType.NorthWest:
+                return Anime.DirectionType.SouthEast;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    public static Anime.DirectionType GetRandomDirection()
+    {
+        int random = Random.Range(0, 8);
+        switch (random)
+        {
+            case 0:
+                return Anime.DirectionType.North;
+            case 1:
+                return Anime.DirectionType.NorthEast;
+            case 2:
+                return Anime.DirectionType.East;
+            case 3:
+                return Anime.DirectionType.SouthEast;
+            case 4:
+                return Anime.DirectionType.South;
+            case 5:
+                return Anime.DirectionType.SouthWest;
+            case 6:
+                return Anime.DirectionType.West;
+            case 7:
+                return Anime.DirectionType.NorthWest;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    // 获取上一个方向 左旋
+    public static Anime.DirectionType GetPrevDirection(Anime.DirectionType directionType)
+    {
+        switch (directionType)
+        {
+            case Anime.DirectionType.North:
+                return Anime.DirectionType.NorthWest;
+            case Anime.DirectionType.NorthEast:
+                return Anime.DirectionType.North;
+            case Anime.DirectionType.East:
+                return Anime.DirectionType.NorthEast;
+            case Anime.DirectionType.SouthEast:
+                return Anime.DirectionType.East;
+            case Anime.DirectionType.South:
+                return Anime.DirectionType.SouthEast;
+            case Anime.DirectionType.SouthWest:
+                return Anime.DirectionType.South;
+            case Anime.DirectionType.West:
+                return Anime.DirectionType.SouthWest;
+            case Anime.DirectionType.NorthWest:
+                return Anime.DirectionType.West;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    public static Anime.DirectionType GetDoublePrevDirection(Anime.DirectionType directionType)
+    {
+        switch (directionType)
+        {
+            case Anime.DirectionType.North:
+                return Anime.DirectionType.West;
+            case Anime.DirectionType.NorthEast:
+                return Anime.DirectionType.NorthWest;
+            case Anime.DirectionType.East:
+                return Anime.DirectionType.North;
+            case Anime.DirectionType.SouthEast:
+                return Anime.DirectionType.NorthEast;
+            case Anime.DirectionType.South:
+                return Anime.DirectionType.East;
+            case Anime.DirectionType.SouthWest:
+                return Anime.DirectionType.SouthEast;
+            case Anime.DirectionType.West:
+                return Anime.DirectionType.South;
+            case Anime.DirectionType.NorthWest:
+                return Anime.DirectionType.SouthWest;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    // 获取下一个方向 右旋
+    public static Anime.DirectionType GetNextDirection(Anime.DirectionType directionType)
+    {
+        switch (directionType)
+        {
+            case Anime.DirectionType.North:
+                return Anime.DirectionType.NorthEast;
+            case Anime.DirectionType.NorthEast:
+                return Anime.DirectionType.East;
+            case Anime.DirectionType.East:
+                return Anime.DirectionType.SouthEast;
+            case Anime.DirectionType.SouthEast:
+                return Anime.DirectionType.South;
+            case Anime.DirectionType.South:
+                return Anime.DirectionType.SouthWest;
+            case Anime.DirectionType.SouthWest:
+                return Anime.DirectionType.West;
+            case Anime.DirectionType.West:
+                return Anime.DirectionType.NorthWest;
+            case Anime.DirectionType.NorthWest:
+                return Anime.DirectionType.North;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    // 获取下第二个方向
+    public static Anime.DirectionType GetDoubleNextDirection(Anime.DirectionType directionType)
+    {
+        switch (directionType)
+        {
+            case Anime.DirectionType.North:
+                return Anime.DirectionType.East;
+            case Anime.DirectionType.NorthEast:
+                return Anime.DirectionType.SouthEast;
+            case Anime.DirectionType.East:
+                return Anime.DirectionType.South;
+            case Anime.DirectionType.SouthEast:
+                return Anime.DirectionType.SouthWest;
+            case Anime.DirectionType.South:
+                return Anime.DirectionType.West;
+            case Anime.DirectionType.SouthWest:
+                return Anime.DirectionType.NorthWest;
+            case Anime.DirectionType.West:
+                return Anime.DirectionType.North;
+            case Anime.DirectionType.NorthWest:
+                return Anime.DirectionType.NorthEast;
+            default:
+                return Anime.DirectionType.East;
+        }
+    }
+    
+    public static List<uint> TestSerial = new List<uint>()
+        {
+            // 旧版单位
+            // 100000, 100001, 100002, 100003, 100004, 100005, 100006, 100007, 100008, 100009, 100010, 100011, 100012,
+            // 100013, 100014, 100015, 100016, 100017, 100018, 100019, 100020, 100021, 100022, 100023, 100025, 100026,
+            // 100027, 100028, 100029, 100030, 100031, 100032, 100033, 100034, 100035, 100036, 100037, 100038, 100039,
+            // 100040, 100041, 100042, 100043, 100044, 100045, 100046, 100047, 100048, 100050, 100051, 100052, 100053,
+            // 100054, 100055, 100056, 100057, 100058, 100059, 100060, 100061, 100062, 100063, 100064, 100065, 100066,
+            // 100067, 100068, 100069, 100070, 100071, 100072, 100073, 100075, 100076, 100077, 100078, 100079, 100080,
+            // 100081, 100082, 100083, 100084, 100085, 100086, 100087, 100088, 100089, 100090, 100091, 100092, 100093,
+            // 100094, 100095, 100096, 100097, 100098, 100100, 100101, 100102, 100103, 100104, 100105, 100106, 100107,
+            // 100108, 100109, 100110, 100111, 100112, 100113, 100114, 100115, 100116, 100117, 100118, 100119, 100120,
+            // 100121, 100122, 100123, 100125, 100126, 100127, 100128, 100129, 100130, 100131, 100132, 100133, 100134,
+            // 100135, 100136, 100137, 100138, 100139, 100140, 100141, 100142, 100143, 100144, 100145, 100146, 100147,
+            // 100148, 100150, 100151, 100152, 100153, 100154, 100155, 100156, 100157, 100158, 100159, 100160, 100161,
+            // 100162, 100163, 100164, 100165, 100166, 100167, 100168, 100169, 100170, 100171, 100172, 100173, 100250,
+            // 100251, 100252, 100253, 100254, 100255, 100256, 100257, 100258, 100259, 100260, 100261, 100262, 100263,
+            // 100264, 100265, 100266, 100267, 100268, 100269, 100270, 100271, 100272, 100273, 100275, 100276, 100277,
+            // 100278, 100279, 100280, 100281, 100282, 100283, 100284, 100285, 100286, 100287, 100288, 100289, 100290,
+            // 100291, 100292, 100293, 100294, 100295, 100296, 100297, 100298, 100300, 100301, 100302, 100303, 100304,
+            // 100305, 100306, 100307, 100308, 100309, 100310, 100311, 100312, 100313, 100314, 100315, 100316, 100317,
+            // 100318, 100319, 100320, 100321, 100322, 100323, 100325, 100326, 100327, 100328, 100329, 100330, 100331,
+            // 100332, 100333, 100334, 100335, 100336, 100337, 100338, 100339, 100340, 100341, 100342, 100343, 100344,
+            // 100345, 100346, 100347, 100348, 100350, 100351, 100352, 100353, 100354, 100355, 100356, 100357, 100358,
+            // 100359, 100360, 100361, 100362, 100363, 100364, 100365, 100366, 100367, 100368, 100369, 100370, 100371,
+            // 100372, 100373, 100375, 100376, 100377, 100378, 100379, 100380, 100381, 100382, 100383, 100384, 100385,
+            // 100386, 100387, 100388, 100389, 100390, 100391, 100392, 100393, 100394, 100395, 100396, 100397, 100398,
+            // 100400, 100401, 100402, 100403, 100404, 100405, 100406, 100407, 100408, 100409, 100410, 100411, 100412,
+            // 100413, 100414, 100415, 100416, 100417, 100418, 100419, 100420, 100421, 100422, 100423, 100425, 100426,
+            // 100427, 100428, 100429, 100430, 100450, 100451, 100452, 100453, 100454, 100455, 100475, 100476, 100477,
+            // 100478, 100479, 100480, 100500, 100501, 100502, 100503, 100504, 100505, 100525, 100526, 100527, 100528,
+            // 100529, 100530, 100550, 100551, 100552, 100553, 100554, 100555, 100575, 100576, 100577, 100578, 100579,
+            // 100580, 100600, 100601, 100602, 100603, 100604, 100605, 100625, 100626, 100627, 100628, 100629, 100630,
+            // 100650, 100651, 100652, 100653, 100654, 100655, 100675, 100676, 100677, 100678, 100679, 100680, 100700,
+            // 100701, 100702, 100703, 100704, 100705, 100725, 100726, 100727, 100728, 100729, 100730, 100750, 100751,
+            // 100752, 100753, 100754, 100755, 100800, 100801, 100802, 100803, 100804, 100805, 100900, 100901,
+
+            // 新版单位
+            105000, 105001, 105002, 105003, 105004, 105005, 105006, 105007, 105008, 105009, 105010, 105011, 105012,
+            105013, 105014, 105014, 105016, 105017, 105018, 105019, 105020, 105021, 105022, 105023, 105025, 105026,
+            105027, 105028, 105029, 105030, 105031, 105032, 105033, 105034, 105035, 105036, 105037, 105038, 105039,
+            105040, 105041, 105042, 105043, 105044, 105045, 105046, 105047, 105048, 105050, 105051, 105052, 105053,
+            105054, 105055, 105056, 105057, 105058, 105059, 105060, 105061, 105062, 105063, 105064, 105065, 105066,
+            105067, 105068, 105069, 105070, 105071, 105072, 105073, 105075, 105076, 105077, 105078, 105079, 105080,
+            105081, 105082, 105083, 105084, 105085, 105086, 105087, 105088, 105089, 105090, 105091, 105092, 105093,
+            105094, 105095, 105096, 105097, 105098, 105100, 105101, 105102, 105103, 105104, 105105, 105106, 105107,
+            105108, 105109, 105110, 105111, 105112, 105113, 105114, 105115, 105116, 105117, 105118, 105119, 105120,
+            105121, 105122, 105123, 105125, 105126, 105127, 105128, 105129, 105130, 105131, 105132, 105133, 105134,
+            105135, 105136, 105137, 105138, 105139, 105140, 105141, 105142, 105143, 105144, 105145, 105146, 105147,
+            105148, 105150, 105151, 105152, 105153, 105154, 105155, 105156, 105157, 105158, 105159, 105160, 105161,
+            105162, 105163, 105164, 105165, 105166, 105167, 105168, 105169, 105170, 105171, 105172, 105173, 105250,
+            105251, 105252, 105253, 105254, 105255, 105256, 105257, 105258, 105259, 105260, 105261, 105262, 105263,
+            105264, 105265, 105266, 105267, 105268, 105269, 105270, 105271, 105272, 105273, 105275, 105276, 105277,
+            105278, 105279, 105280, 105281, 105282, 105283, 105284, 105285, 105286, 105287, 105288, 105289, 105290,
+            105291, 105292, 105293, 105294, 105295, 105296, 105297, 105298, 105300, 105301, 105302, 105303, 105304,
+            105305, 105306, 105307, 105308, 105309, 105310, 105311, 105312, 105313, 105314, 105315, 105316, 105317,
+            105318, 105319, 105320, 105321, 105322, 105323, 105325, 105326, 105327, 105328, 105329, 105330, 105331, 105332,
+            105333, 105334, 105335, 105336, 105337, 105338, 105339, 105340, 105341, 105342, 105343, 105344, 105345,
+            105346, 105347, 105348, 105350, 105351, 105352, 105353, 105354, 105355, 105356, 105357, 105358, 105359,
+            105360, 105361, 105362, 105363, 105364, 105365, 105366, 105367, 105368, 105369, 105370, 105371, 105372,
+            105373, 105375, 105376, 105377, 105378, 105379, 105380, 105381, 105382, 105383, 105384, 105385, 105386,
+            105387, 105388, 105389, 105390, 105391, 105392, 105393, 105394, 105395, 105396, 105397, 105398, 105400,
+            105401, 105402, 105403, 105404, 105405, 105406, 105407, 105408, 105409, 105410, 105411, 105412, 105413,
+            105414, 105415, 105416, 105417, 105418, 105419, 105420, 105421, 105422, 105423, 106000, 106001, 106002,
+            106003, 106004, 106005, 106006, 106007, 106008, 106009, 106010, 106011, 106012, 106013, 106014, 106015,
+            106016, 106017, 106018, 106019, 106020, 106021, 106022, 106023, 106025, 106026, 106027, 106028, 106029,
+            106030, 106031, 106032, 106033, 106034, 106035, 106036, 106037, 106038, 106039, 106040, 106041, 106042,
+            106043, 106044, 106045, 106046, 106047, 106048, 106050, 106051, 106052, 106053, 106054, 106055, 106056,
+            106057, 106058, 106059, 106060, 106061, 106062, 106063, 106064, 106065, 106066, 106067, 106068, 106069,
+            106070, 106071, 106072, 106073, 106075, 106076, 106077, 106078, 106079, 106080, 106081, 106082, 106083,
+            106084, 106085, 106086, 106087, 106088, 106089, 106090, 106091, 106092, 106093, 106094, 106095, 106096,
+            106097, 106098, 106100, 106101, 106102, 106103, 106104, 106105, 106106, 106107, 106108, 106109, 106110,
+            106111, 106112, 106113, 106114, 106115, 106116, 106117, 106118, 106119, 106120, 106121, 106122, 106123,
+            106125, 106126, 106127, 106128, 106129, 106130, 106131, 106132, 106133, 106134, 106135, 106136, 106137,
+            106138, 106139, 106140, 106141, 106142, 106143, 106144, 106145, 106146, 106147, 106148, 106150, 106151,
+            106152, 106153, 106154, 106155, 106156, 106157, 106158, 106159, 106160, 106161, 106162, 106163, 106164,
+            106165, 106166, 106167, 106168, 106169, 106170, 106171, 106172, 106173, 106250, 106251, 106252, 106253,
+            106254, 106255, 106256, 106257, 106258, 106259, 106260, 106261, 106262, 106263, 106264, 106265, 106266,
+            106267, 106268, 106269, 106270, 106271, 106272, 106273, 106275, 106276, 106277, 106278, 106279, 106280,
+            106281, 106282, 106283, 106284, 106285, 106286, 106287, 106288, 106289, 106290, 106291, 106292, 106293,
+            106294, 106295, 106296, 106297, 106298, 106300, 106301, 106302, 106303, 106304, 106305, 106306, 106307,
+            106308, 106309, 106310, 106311, 106312, 106313, 106314, 106315, 106316, 106317, 106318, 106319, 106320,
+            106321, 106322, 106323, 106325, 106326, 106327, 106328, 106329, 106330, 106331, 106332, 106333, 106334,
+            106335, 106336, 106337, 106338, 106339, 106340, 106341, 106342, 106343, 106344, 106345, 106346, 106347,
+            106348, 106350, 106351, 106352, 106353, 106354, 106355, 106356, 106357, 106358, 106359, 106360, 106361,
+            106362, 106363, 106364, 106365, 106366, 106367, 106368, 106369, 106370, 106371, 106372, 106373, 106375,
+            106376, 106377, 106378, 106379, 106380, 106381, 106382, 106383, 106384, 106385, 106386, 106387, 106388,
+            106389, 106390, 106391, 106392, 106393, 106394, 106395, 106396, 106397, 106398, 106400, 106401, 106402,
+            106403, 106404, 106405, 106406, 106407, 106408, 106409, 106410, 106411, 106412, 106413, 106414, 106415,
+            106416, 106417, 106418, 106419, 106420, 106421, 106422, 106423, 106425, 106426, 106427, 106428, 106429,
+            106430, 106450, 106451, 106452, 106453, 106454, 106455, 106475, 106476, 106477, 106478, 106479, 106480,
+            106500, 106501, 106502, 106503, 106504, 106505, 106525, 106526, 106527, 106528, 106529, 106530, 106550,
+            106551, 106552, 106553, 106554, 106555, 106575, 106576, 106577, 106578, 106579, 106580, 106600, 106601,
+            106602, 106603, 106604, 106605, 106625, 106626, 106627, 106628, 106629, 106630, 106650, 106651, 106652,
+            106653, 106654, 106655, 106675, 106676, 106677, 106678, 106679, 106680, 106700, 106701, 106702, 106703,
+            106704, 106705, 106725, 106726, 106727, 106728, 106729, 106730, 106750, 106751, 106752, 106753, 106754,
+            106755
+        };
+    public static uint GetRandomSerial()
+    {
+        int random = Random.Range(0, TestSerial.Count);
+        return TestSerial[random];
+    }
+
+    public static Anime.ActionType GetNextAction(Anime.ActionType actionType)
+    {
+        int action = (int)actionType;
+        action++;
+        if (action > 20) action = 0;
+        return (Anime.ActionType)action;
+    }
+}

+ 11 - 0
example/Script/Util.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: aa7779584b87f43e3907386264b0d5a3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
example/Temp.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1da0e7469c9404ad3bc986727ab9be5a
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
example/Temp/AnimePlayerProps.jpg


+ 135 - 0
example/Temp/AnimePlayerProps.jpg.meta

@@ -0,0 +1,135 @@
+fileFormatVersion: 2
+guid: 3d759879c7a8a44dcb7cc5ea3d71c010
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 12
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMasterTextureLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Android
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Server
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    nameFileIdTable: {}
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
example/Temp/MapTileSorting.png


+ 135 - 0
example/Temp/MapTileSorting.png.meta

@@ -0,0 +1,135 @@
+fileFormatVersion: 2
+guid: 7c892a72def28457cb5242d0a5730b38
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 12
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMasterTextureLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 1
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Android
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Server
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    nameFileIdTable: {}
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
example/Temp/minimap_tile.png


+ 135 - 0
example/Temp/minimap_tile.png.meta

@@ -0,0 +1,135 @@
+fileFormatVersion: 2
+guid: 2ddbf947884314f3591bfa68d72e4cea
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 12
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMasterTextureLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 0
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 0
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 1
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Server
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: WebGL
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    nameFileIdTable: {}
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: