Kaynağa Gözat

初次上传

taochangchun 1 ay önce
işleme
fa100e1839

+ 26 - 0
.gitignore

@@ -0,0 +1,26 @@
1
+ExportedObj/
2
+.consulo/
3
+*.csproj
4
+*.unityproj
5
+*.sln
6
+*.suo
7
+*.tmp
8
+*.user
9
+*.userprefs
10
+*.pidb
11
+*.booproj
12
+*.svd
13
+*.pdb
14
+*.opendb
15
+
16
+# Unity3D generated meta files
17
+*.pidb.meta
18
+*.pdb.meta
19
+*.asset
20
+
21
+# Unity3D Generated File On Crash Reports
22
+sysinfo.txt
23
+
24
+# Builds
25
+*.apk
26
+*.unitypackage

+ 8 - 0
Editor.meta

@@ -0,0 +1,8 @@
1
+fileFormatVersion: 2
2
+guid: 07ad215593da79047a57f641b1e5a4ad
3
+folderAsset: yes
4
+DefaultImporter:
5
+  externalObjects: {}
6
+  userData: 
7
+  assetBundleName: 
8
+  assetBundleVariant: 

+ 55 - 0
Editor/AssetBudleConfig.cs

@@ -0,0 +1,55 @@
1
+using System.Collections.Generic;
2
+using UnityEngine;
3
+using System;
4
+
5
+namespace TModule.Editor
6
+{
7
+    [Serializable]
8
+    public class AssetBudleConfig : ScriptableObject
9
+    {
10
+        public List<AssetBundleEntity> m_AB = new List<AssetBundleEntity>();
11
+    }
12
+    [Serializable]
13
+    public class AssetBundleEntity
14
+    {
15
+        /// <summary>
16
+        /// ID
17
+        /// </summary>
18
+        public string m_key;
19
+
20
+        /// <summary>
21
+        /// 名称
22
+        /// </summary>
23
+        public string m_name;
24
+
25
+        /// <summary>
26
+        /// 标签
27
+        /// </summary>
28
+        public string m_tag;
29
+
30
+        /// <summary>
31
+        /// 版本号
32
+        /// </summary>
33
+        public int m_version;
34
+
35
+        /// <summary>
36
+        /// 大小
37
+        /// </summary>
38
+        public long m_size;
39
+
40
+        /// <summary>
41
+        /// 打包路径
42
+        /// </summary>
43
+        public string m_toPath;
44
+
45
+        /// <summary>
46
+        /// 是否是文件夹
47
+        /// </summary>
48
+        public bool m_isFolder;
49
+
50
+        /// <summary>
51
+        /// 是否是初始资源
52
+        /// </summary>
53
+        public bool m_isFirstData;
54
+    }
55
+}

+ 11 - 0
Editor/AssetBudleConfig.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: a2d4bb0157c733647aa12789ecab546e
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 374 - 0
Editor/AssetBudleTool.cs

@@ -0,0 +1,374 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.IO;
5
+using System.Security.Cryptography;
6
+using System.Text;
7
+using TModule.Runtime;
8
+using UnityEditor;
9
+using UnityEngine;
10
+using LitJson;
11
+
12
+namespace TModule.Editor
13
+{
14
+    public class AssetBudleTool : EditorWindow
15
+    {
16
+        private string AssetBudleConfigName= "AssetBundleConfig.asset";
17
+        private string AssetBudleConfigPath;
18
+        private string AssetbudleToolConfigName = "BudleToolConfig.asset";
19
+        private  string AssetbudleToolConfigPath;
20
+        private AssetBudleConfig _list;
21
+        private AssetBudleConfig BudleConfig
22
+        {
23
+            get
24
+            {
25
+                _list = _list ?? AssetDatabase.LoadAssetAtPath<AssetBudleConfig>(AssetBudleConfigPath);
26
+                if(_list==null)
27
+                {
28
+                    _list = CreateInstance<AssetBudleConfig>();
29
+                    AssetDatabase.CreateAsset(_list, AssetBudleConfigPath);
30
+                }
31
+                return _list;
32
+            }
33
+            set => _list = value;
34
+        }
35
+
36
+        private AssetBudleToolConfig _toolConfig;
37
+
38
+        private AssetBudleToolConfig BudleToolConfig
39
+        {
40
+            get
41
+            {
42
+                _toolConfig = _toolConfig ?? AssetDatabase.LoadAssetAtPath<AssetBudleToolConfig>(AssetbudleToolConfigPath);
43
+                if(_toolConfig==null)
44
+                {
45
+                    _toolConfig = CreateInstance<AssetBudleToolConfig>();
46
+                    AssetDatabase.CreateAsset(_toolConfig, AssetbudleToolConfigPath);
47
+                }
48
+                return _toolConfig;
49
+            }
50
+            set => _toolConfig = value;
51
+        }
52
+
53
+        private static List<VersionDataEntity> versionDatas = new List<VersionDataEntity>();
54
+
55
+        private Vector2 _scorllView = Vector2.zero;
56
+
57
+#if UNITY_STANDALONE_WIN
58
+        private BuildTarget _buildTarget = BuildTarget.StandaloneWindows64;
59
+#elif UNITY_ANDROID
60
+        private BuildTarget _buildTarget = BuildTarget.Android;
61
+#elif UNITY_IPHON
62
+        private BuildTarget _buildTarget = BuildTarget.iOS;
63
+#endif
64
+
65
+        [MenuItem("TModule/热更/AssetBudleTool")]
66
+        public static void OpenWin()
67
+        {
68
+            AssetBudleTool win = GetWindow<AssetBudleTool>();
69
+            win.maxSize = new Vector2(800, 400);
70
+            win.titleContent.text = "ABTool";
71
+            win.titleContent.image = EditorGUIUtility.IconContent("PrefabModel Icon").image;
72
+            win.Show();
73
+        }
74
+
75
+        private void OnEnable()
76
+        {
77
+            var ms = MonoScript.FromScriptableObject(this);
78
+            var path = AssetDatabase.GetAssetPath(ms);
79
+            path = Path.GetDirectoryName(path);
80
+            AssetBudleConfigPath = Path.Combine(path, AssetBudleConfigName);
81
+            AssetbudleToolConfigPath = Path.Combine(path, AssetbudleToolConfigName);
82
+        }
83
+
84
+        private void OnGUI()
85
+        {
86
+            using (new EditorGUILayout.HorizontalScope("Box"))
87
+            {
88
+                EditorGUILayout.LabelField("打包平台:", GUILayout.Width(60));
89
+                _buildTarget = (BuildTarget)EditorGUILayout.EnumPopup(_buildTarget);
90
+                EditorGUILayout.LabelField("输出路径:", GUILayout.Width(60));
91
+                BudleToolConfig.m_savePath = EditorGUILayout.TextField(BudleToolConfig.m_savePath);
92
+                if (GUILayout.Button(EditorGUIUtility.IconContent("Project@2x").image, GUILayout.Height(20), GUILayout.Width(40)))
93
+                {
94
+                    try
95
+                    {
96
+                        BudleToolConfig.m_savePath = EditorUtility.OpenFolderPanel("AB包输出路径", "Assets", "Assets");
97
+                    }
98
+                    catch (Exception e)
99
+                    {
100
+                        Debug.Log(e.Message);
101
+                    }
102
+                }
103
+            }
104
+            float _width = position.width / 6;
105
+            using (new EditorGUILayout.HorizontalScope("Box"))
106
+            {
107
+                EditorGUILayout.LabelField("包名", GUILayout.Width(_width * 4));
108
+                EditorGUILayout.LabelField("文件夹", GUILayout.Width(_width));
109
+                EditorGUILayout.LabelField("操作");
110
+            }
111
+
112
+            _scorllView = EditorGUILayout.BeginScrollView(_scorllView);
113
+            for (int i = 0; i < BudleConfig.m_AB.Count; i++)
114
+            {
115
+                using (new EditorGUILayout.HorizontalScope())
116
+                {
117
+                    BudleConfig.m_AB[i].m_name = EditorGUILayout.TextField(BudleConfig.m_AB[i].m_name, GUILayout.Width(_width * 4));
118
+                    BudleConfig.m_AB[i].m_isFolder = EditorGUILayout.Toggle(BudleConfig.m_AB[i].m_isFolder, GUILayout.Width(_width));
119
+                    if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Trash").image, GUILayout.Height(20)))
120
+                    {
121
+                        BudleConfig.m_AB.Remove(BudleConfig.m_AB[i]);
122
+                    }
123
+                }
124
+            }
125
+            if (GUILayout.Button(EditorGUIUtility.IconContent("CreateAddNew@2x").image, GUILayout.Height(30), GUILayout.Width(30)))
126
+            {
127
+                BudleConfig.m_AB.Add(new AssetBundleEntity());
128
+            }
129
+            EditorGUILayout.EndScrollView();
130
+
131
+            if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
132
+            {
133
+                if (Event.current.type == EventType.DragUpdated)
134
+                    DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
135
+                else if (Event.current.type == EventType.DragExited)
136
+                {
137
+                    if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
138
+                    {
139
+                        for (int i = 0; i < DragAndDrop.paths.Length; i++)
140
+                        {
141
+                            if (BudleConfig.m_AB.Find(p => p.m_name == DragAndDrop.paths[i]) == null)
142
+                                BudleConfig.m_AB.Add(new AssetBundleEntity()
143
+                                { m_name = DragAndDrop.paths[i] });
144
+                        }
145
+                    }
146
+                }
147
+            }
148
+
149
+            using (new EditorGUILayout.HorizontalScope())
150
+            {
151
+                EditorGUILayout.LabelField("将打包资源拷贝到StreamingAssets文件夹", GUILayout.Width(230));
152
+                BudleToolConfig.m_copyToStreamingAssets = EditorGUILayout.Toggle(BudleToolConfig.m_copyToStreamingAssets);
153
+            }
154
+
155
+            if (GUILayout.Button("构建AssetBundle"))
156
+            {
157
+                OnAssetBundleCallBack();
158
+            }
159
+        }
160
+
161
+        /// <summary>
162
+        /// 打包回调
163
+        /// </summary>
164
+        private void OnAssetBundleCallBack()
165
+        {
166
+            string tartgetPath = BudleToolConfig.m_savePath + "/" + _buildTarget.ToString();
167
+            if (!Directory.Exists(tartgetPath))
168
+                Directory.CreateDirectory(tartgetPath);
169
+            SetABName();
170
+            BuildPipeline.BuildAssetBundles(tartgetPath, BuildAssetBundleOptions.None, _buildTarget);
171
+
172
+            if (BudleToolConfig.m_copyToStreamingAssets)
173
+                CopyToStreamingAssets();
174
+
175
+            OnCreateVersionText();
176
+            AssetDatabase.Refresh();
177
+        }
178
+
179
+        private void SetABName()
180
+        {
181
+            for (int i = 0; i < BudleConfig.m_AB.Count; i++)
182
+            {
183
+                AssetBundleEntity assetBudle = BudleConfig.m_AB[i];
184
+                if (assetBudle.m_isFolder)
185
+                {
186
+                    string[] floderArr = new string[] {GetAbsolutePath(assetBudle.m_name) };
187
+                    SaveFolderSettings(floderArr);
188
+                }
189
+                else
190
+                {
191
+                    SaveFileSettings(Application.dataPath + "/" + assetBudle.m_name);
192
+                }
193
+            }
194
+
195
+        }
196
+
197
+        private void SaveFolderSettings(string[] folderArr)
198
+        {
199
+            foreach (string floderPath in folderArr)
200
+            {
201
+                string[] arrFile = Directory.GetFiles(floderPath);
202
+
203
+                foreach (string filePah in arrFile)
204
+                {
205
+                    SaveFileSettings(filePah);
206
+                }
207
+
208
+                string[] arrFolder = Directory.GetDirectories(floderPath);
209
+                SaveFolderSettings(arrFolder);
210
+            }
211
+        }
212
+
213
+        private void SaveFileSettings(string filePath)
214
+        {
215
+            FileInfo file = new FileInfo(filePath);
216
+            if (!file.Extension.Equals(".meta", StringComparison.CurrentCultureIgnoreCase))
217
+            {
218
+                int index = filePath.IndexOf("Assets/", StringComparison.CurrentCultureIgnoreCase);
219
+
220
+                string newPath = filePath.Substring(index);
221
+
222
+                string fileName = newPath.Substring(newPath.IndexOf("Assets/")).Replace(file.Extension, "");
223
+
224
+                string variant = file.Extension.Equals(".unity", StringComparison.CurrentCultureIgnoreCase) ? "unity3d" : "assetbundle";
225
+
226
+                AssetImporter importer = AssetImporter.GetAtPath(newPath);
227
+                importer.SetAssetBundleNameAndVariant(fileName, variant);
228
+                importer.SaveAndReimport();
229
+            }
230
+        }
231
+
232
+        private void CopyToStreamingAssets()
233
+        {
234
+            string toPath = Application.streamingAssetsPath;
235
+            string tartgetPath = BudleToolConfig.m_savePath + "/" + _buildTarget.ToString();
236
+            CopyDirectory(tartgetPath, toPath,true);
237
+            AssetDatabase.Refresh();
238
+        }
239
+
240
+        /// <summary>
241
+        /// 创建版本文件
242
+        /// </summary>
243
+        private void OnCreateVersionText()
244
+        {
245
+            string strVersionJsonPath = $"{BudleToolConfig.m_savePath}/{_buildTarget.ToString()}/VersionFile.json";
246
+            versionDatas.Clear();
247
+            if (File.Exists(strVersionJsonPath))
248
+                File.Delete(strVersionJsonPath);
249
+
250
+            StringBuilder sbContent = new StringBuilder();
251
+
252
+            DirectoryInfo directory = new DirectoryInfo(BudleToolConfig.m_savePath);
253
+            FileInfo[] arrfiles = directory.GetFiles("*", SearchOption.AllDirectories);
254
+            for (int i = 0; i < arrfiles.Length; i++)
255
+            {
256
+                FileInfo file = arrfiles[i];
257
+
258
+                string fullName = file.FullName;
259
+                string md5 = GetFileMD5(fullName);
260
+                if (md5 == null) continue;
261
+
262
+                string subPath = $"{BudleToolConfig.m_savePath}/{_buildTarget.ToString()}";
263
+                versionDatas.Add(new VersionDataEntity()
264
+                {
265
+                    m_fullName = fullName.Substring(fullName.IndexOf(subPath) + subPath.Length + 2),
266
+                    m_md5 = md5,
267
+                    m_size = Mathf.Ceil(file.Length / 1024.0f)
268
+                });
269
+            }
270
+
271
+            WriteJsonData(versionDatas, strVersionJsonPath);
272
+        }
273
+
274
+        private void OnDisable()
275
+        {
276
+            EditorUtility.SetDirty(_list);
277
+            EditorUtility.SetDirty(BudleToolConfig);
278
+            AssetDatabase.SaveAssets();
279
+        }
280
+
281
+        public string GetAbsolutePath(string path)
282
+        {
283
+            string _path = Application.dataPath.Remove(Application.dataPath.LastIndexOf('/') + 1);
284
+            return _path + path;
285
+        }
286
+
287
+        /// <summary>
288
+        /// 拷贝文件夹
289
+        /// </summary>
290
+        /// <param name="sourceDirName"></param>
291
+        /// <param name="destDirName"></param>
292
+        /// <param name="isOverlay">是否覆盖已有同名文件</param>
293
+        public void CopyDirectory(string sourceDirName, string destDirName, bool isOverlay = false)
294
+        {
295
+            try
296
+            {
297
+                if (!Directory.Exists(destDirName))
298
+                {
299
+                    Directory.CreateDirectory(destDirName);
300
+                    File.SetAttributes(destDirName, File.GetAttributes(sourceDirName));
301
+                }
302
+
303
+                if (destDirName[destDirName.Length - 1] != Path.DirectorySeparatorChar)
304
+                    destDirName = destDirName + Path.DirectorySeparatorChar;
305
+
306
+                string[] files = Directory.GetFiles(sourceDirName);
307
+                foreach (string file in files)
308
+                {
309
+                    if (File.Exists(destDirName + Path.GetFileName(file)) && !isOverlay)
310
+                        continue;
311
+                    FileInfo fileInfo = new FileInfo(file);
312
+                    if (fileInfo.Extension.Equals(".meta", StringComparison.CurrentCultureIgnoreCase))
313
+                        continue;
314
+
315
+                    File.Copy(file, destDirName + Path.GetFileName(file), true);
316
+                    File.SetAttributes(destDirName + Path.GetFileName(file), FileAttributes.Normal);
317
+                }
318
+
319
+                string[] dirs = Directory.GetDirectories(sourceDirName);
320
+                foreach (string dir in dirs)
321
+                {
322
+                    CopyDirectory(dir, destDirName + Path.GetFileName(dir), isOverlay);
323
+                }
324
+            }
325
+            catch (Exception ex)
326
+            {
327
+                throw ex;
328
+            }
329
+        }
330
+
331
+        /// <summary>
332
+        /// 写入数据
333
+        /// </summary>
334
+        /// <param name="data">数据</param>
335
+        /// <param name="path">文件完整路径</param>
336
+        public static void WriteJsonData(object data, string path)
337
+        {
338
+            string json = JsonMapper.ToJson(data);
339
+            using (StreamWriter sw = new StreamWriter(path))
340
+            {
341
+                //保存数据
342
+                sw.WriteLine(json);
343
+                //关闭文档
344
+                sw.Close();
345
+                sw.Dispose();
346
+            }
347
+        }
348
+
349
+        /// <summary>
350
+        /// 获取文件MD5
351
+        /// </summary>
352
+        /// <param name="filePath"></param>
353
+        /// <returns></returns>
354
+        public static string GetFileMD5(string filePath)
355
+        {
356
+            if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
357
+                return null;
358
+
359
+            try
360
+            {
361
+                FileStream file = new FileStream(filePath, FileMode.Open);
362
+                MD5 mD5 = new MD5CryptoServiceProvider();
363
+                byte[] byteResult = mD5.ComputeHash(file);
364
+                string strResult = BitConverter.ToString(byteResult);
365
+                strResult = strResult.Replace("-", "");
366
+                return strResult;
367
+            }
368
+            catch
369
+            {
370
+                return null;
371
+            }
372
+        }
373
+    }
374
+}

+ 11 - 0
Editor/AssetBudleTool.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: 43731dda4c05c934e8c230876a8c428d
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 15 - 0
Editor/AssetBudleToolConfig.cs

@@ -0,0 +1,15 @@
1
+using System.Collections;
2
+using System.Collections.Generic;
3
+using UnityEngine;
4
+using System;
5
+
6
+namespace TModule.Editor
7
+{
8
+    [Serializable]
9
+    public class AssetBudleToolConfig : ScriptableObject
10
+    {
11
+        public string m_savePath;
12
+
13
+        public bool m_copyToStreamingAssets;
14
+    }
15
+}

+ 11 - 0
Editor/AssetBudleToolConfig.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: 026905a26e66dda4ea85e5b8fbd10bc8
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: 

+ 8 - 0
Editor/AssetBundleConfig.asset.meta

@@ -0,0 +1,8 @@
1
+fileFormatVersion: 2
2
+guid: 16ec825a5a31d264b9ad36aa0df70abe
3
+NativeFormatImporter:
4
+  externalObjects: {}
5
+  mainObjectFileID: 11400000
6
+  userData: 
7
+  assetBundleName: 
8
+  assetBundleVariant: 

+ 8 - 0
Editor/BudleToolConfig.asset.meta

@@ -0,0 +1,8 @@
1
+fileFormatVersion: 2
2
+guid: 2221998dbb651da448240ee2e98c22d2
3
+NativeFormatImporter:
4
+  externalObjects: {}
5
+  mainObjectFileID: 11400000
6
+  userData: 
7
+  assetBundleName: 
8
+  assetBundleVariant: 

+ 23 - 0
VersionDataEntity.cs

@@ -0,0 +1,23 @@
1
+using System;
2
+
3
+namespace TModule.Runtime
4
+{
5
+    [Serializable]
6
+    public class VersionDataEntity
7
+    {
8
+        /// <summary>
9
+        /// ×ÊÔ´Ãû³Æ
10
+        /// </summary>
11
+        public string m_fullName;
12
+
13
+        /// <summary>
14
+        /// MD5
15
+        /// </summary>
16
+        public string m_md5;
17
+
18
+        /// <summary>
19
+        /// ×ÊÔ´´óС£¨K£©
20
+        /// </summary>
21
+        public double m_size;
22
+    }
23
+}

+ 11 - 0
VersionDataEntity.cs.meta

@@ -0,0 +1,11 @@
1
+fileFormatVersion: 2
2
+guid: c26349e8638a4224cbe622331274aa42
3
+MonoImporter:
4
+  externalObjects: {}
5
+  serializedVersion: 2
6
+  defaultReferences: []
7
+  executionOrder: 0
8
+  icon: {instanceID: 0}
9
+  userData: 
10
+  assetBundleName: 
11
+  assetBundleVariant: