com.typhoon.unitysdk 1.0.34 → 1.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/Editor/ApplyTool.cs +29 -6
  2. package/Editor/ExportModule.cs +22 -0
  3. package/Editor/GUIDrawer.cs +22 -0
  4. package/Editor/MD5Tool.cs +53 -0
  5. package/Editor/MD5Tool.cs.meta +11 -0
  6. package/Editor/Orientation.cs +18 -0
  7. package/Editor/Orientation.cs.meta +11 -0
  8. package/Editor/PluginModuleInstaller.cs +432 -0
  9. package/Editor/PluginModuleInstaller.cs.meta +11 -0
  10. package/Editor/PublishSetting.cs +3 -0
  11. package/Editor/PublishSettingGUIDrawer.cs +19 -1
  12. package/Editor/PublishWindow.cs +1 -1
  13. package/Editor/UniEditor.cs +164 -7
  14. package/Editor/VivoMiniConfig.cs +301 -0
  15. package/Editor/VivoMiniConfig.cs.meta +11 -0
  16. package/Editor/WxMiniConfig.cs +4 -19
  17. package/Editor/XGameDotNetZip.dll +0 -0
  18. package/Editor/XGameDotNetZip.dll.meta +33 -0
  19. package/Editor/ZipTool.cs +78 -0
  20. package/Editor/ZipTool.cs.meta +11 -0
  21. package/Editor/bats/create-sign.bat +12 -0
  22. package/Editor/bats/create-sign.bat.meta +7 -0
  23. package/Editor/bats.meta +8 -0
  24. package/Runtime/BaseSdk.cs +64 -0
  25. package/Runtime/HttpGetSuccessResult.cs +23 -0
  26. package/Runtime/HttpGetSuccessResult.cs.meta +11 -0
  27. package/Runtime/HttpPostSuccessResult.cs +30 -0
  28. package/Runtime/HttpPostSuccessResult.cs.meta +11 -0
  29. package/Runtime/Interface.cs +21 -2
  30. package/Runtime/SDKHttpClient.cs +119 -0
  31. package/Runtime/SDKHttpClient.cs.meta +11 -0
  32. package/Runtime/TyphoonSdk.cs +42 -0
  33. package/Sources~/Package/ChinaAndroid.unitypackage +0 -0
  34. package/Sources~/Package/VivoMini.unitypackage +0 -0
  35. package/Sources~/Package/VivoMini.unitypackage.manifest +17 -0
  36. package/package.json +1 -1
@@ -28,6 +28,7 @@ namespace TyphoonUnitySDK
28
28
  { AppChannel.DouyinAndroid, new ApplyDouyinAndroidOrIOS() },
29
29
  { AppChannel.DouyinIOS, new ApplyDouyinAndroidOrIOS() },
30
30
  { AppChannel.GooglePlay, new ApplyGooglePlay() },
31
+ { AppChannel.VivoMini, new ApplyVivoMini() },
31
32
  };
32
33
 
33
34
 
@@ -45,19 +46,19 @@ namespace TyphoonUnitySDK
45
46
  case BuildTarget.Android:
46
47
  {
47
48
  ModifyAndroidPlayerSetting(setting);
48
- Debug.Log($"<color=#3ac9f3>根据发布模式导入更换资源包</color>");
49
+ // Debug.Log($"<color=#3ac9f3>根据发布模式导入更换资源包</color>");
49
50
  }
50
51
  break;
51
52
  case BuildTarget.iOS:
52
53
  {
53
54
  ModifyIOSSetting(setting);
54
- Debug.Log($"<color=#3ac9f3>//TODO//根据发布模式导入更换资源包</color>");
55
+ // Debug.Log($"<color=#3ac9f3>//TODO//根据发布模式导入更换资源包</color>");
55
56
  }
56
57
  break;
57
58
  case BuildTarget.WebGL:
58
59
  {
59
60
  ModifyWebglSetting(setting);
60
- Debug.Log($"<color=#3ac9f3>//TODO//根据发布模式导入更换资源包</color>");
61
+ // Debug.Log($"<color=#3ac9f3>//TODO//根据发布模式导入更换资源包</color>");
61
62
  }
62
63
  break;
63
64
  default:
@@ -141,7 +142,7 @@ namespace TyphoonUnitySDK
141
142
  AddressableSupport.ModifyAAProfileAndVariables(setting);
142
143
  //写入App config
143
144
  WriteAppConfig(setting);
144
- Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
145
+ // Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
145
146
  }
146
147
 
147
148
  /// <summary>
@@ -156,7 +157,7 @@ namespace TyphoonUnitySDK
156
157
  AddressableSupport.ModifyAAProfileAndVariables(setting);
157
158
  //写入App config
158
159
  WriteAppConfig(setting);
159
- Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
160
+ // Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
160
161
  }
161
162
 
162
163
  /// <summary>
@@ -195,7 +196,7 @@ namespace TyphoonUnitySDK
195
196
  AddressableSupport.ModifyAAProfileAndVariables(setting);
196
197
  //写入App config
197
198
  WriteAppConfig(setting);
198
- Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
199
+ // Debug.Log($"<color=#3ac9f3>//TODO//导入资源包...</color>");
199
200
  }
200
201
 
201
202
  /// <summary>
@@ -502,5 +503,27 @@ namespace TyphoonUnitySDK
502
503
  AssetDatabase.Refresh();
503
504
  }
504
505
  }
506
+
507
+
508
+ /*vivo mini*/
509
+ public class ApplyVivoMini : IApply
510
+ {
511
+ public void Apply(PublishSetting setting)
512
+ {
513
+ var pack = UniEditor.PackagePath_VivoMini;
514
+ Debug.Log($"导入... {pack}");
515
+ ImportUnityPackage(pack);
516
+ var manifest_path = $"{pack}.manifest";
517
+ Debug.Log($"读取资源清单...{manifest_path}");
518
+ var manifest = ReadManifest(manifest_path);
519
+ Debug.Log($"清理多余文件...");
520
+ foreach (var folder in MaybeFolder)
521
+ {
522
+ ClearFilesInDirectory(folder, manifest);
523
+ }
524
+
525
+ AssetDatabase.Refresh();
526
+ }
527
+ }
505
528
  }
506
529
  }
@@ -102,6 +102,28 @@ namespace TyphoonUnitySDK
102
102
  ExportUnityPackage(manifest, UniEditor.PackagePath_GooglePlay, out var detail);
103
103
  }
104
104
 
105
+
106
+ [MenuItem("TyphoonSDK/开发者/导出-VivoMini.unitypackage")]
107
+ public static void ExportVivoMini()
108
+ {
109
+ var manifest = new List<string>()
110
+ {
111
+ "Assets/Typhoon_Gen/TyphoonSDK/Runtime/VivoMini",
112
+ };
113
+ if (!MakeSureExport(manifest))
114
+ {
115
+ return;
116
+ }
117
+
118
+ if (!CheckMissFiles(manifest))
119
+ {
120
+ return;
121
+ }
122
+
123
+ ExportUnityPackage(manifest, UniEditor.PackagePath_VivoMini, out var detail);
124
+ }
125
+
126
+
105
127
  /// <summary>
106
128
  /// 导出清单文件到模块
107
129
  /// </summary>
@@ -109,5 +109,27 @@ namespace TyphoonUnitySDK
109
109
  handler?.Invoke();
110
110
  }
111
111
  }
112
+
113
+ /// <summary>
114
+ /// 绘制单选框
115
+ /// </summary>
116
+ public static void DrawPopUpToggle(bool on, Action<bool> setter,
117
+ params GUILayoutOption[] option)
118
+ {
119
+ var txt = on ? "开" : "关";
120
+ if (GUILayout.Button(txt, "PopUp", option))
121
+ {
122
+ var menu = new GenericMenu();
123
+ menu.AddItem(new GUIContent("开"), false, () => setter?.Invoke(true));
124
+ menu.AddItem(new GUIContent("关"), false, () => setter?.Invoke(false));
125
+ menu.ShowAsContext();
126
+ }
127
+ }
128
+
129
+
130
+ private static void ClickOn(ref bool on, bool setter)
131
+ {
132
+ on = setter;
133
+ }
112
134
  }
113
135
  }
@@ -0,0 +1,53 @@
1
+ using System;
2
+ using System.IO;
3
+ using System.Security.Cryptography;
4
+ using System.Text;
5
+
6
+ namespace TyphoonUnitySDK
7
+ {
8
+ /// <summary>
9
+ /// MD5工具
10
+ /// </summary>
11
+ public static class MD5Tool
12
+ {
13
+ public static string GetMD5HashCodeFromFile(string filePath)
14
+ {
15
+ try
16
+ {
17
+ using (FileStream fStream = new FileStream(filePath, FileMode.Open))
18
+ {
19
+ MD5 md5 = new MD5CryptoServiceProvider();
20
+ byte[] retVal = md5.ComputeHash(fStream);
21
+
22
+ StringBuilder builder = new StringBuilder();
23
+ for (int i = 0; i < retVal.Length; i++)
24
+ {
25
+ builder.Append(retVal[i].ToString("X2"));
26
+ }
27
+
28
+ return builder.ToString().ToLower();
29
+ }
30
+ }
31
+ catch (Exception ex)
32
+ {
33
+ throw new Exception("GetMD5HashCodeFromFile() fail,error:" + ex.Message);
34
+ }
35
+ }
36
+
37
+ public static byte[] GetMD5HashBytesFromFile(string filePath)
38
+ {
39
+ try
40
+ {
41
+ using (FileStream fStream = new FileStream(filePath, FileMode.Open))
42
+ {
43
+ MD5 md5 = new MD5CryptoServiceProvider();
44
+ return md5.ComputeHash(fStream);
45
+ }
46
+ }
47
+ catch (Exception ex)
48
+ {
49
+ throw new Exception("GetMD5HashBytesFromFile() fail,error:" + ex.Message);
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 3d13e3175f3b3994ab8d40fe982d62b2
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,18 @@
1
+ using System.Collections;
2
+ using System.Collections.Generic;
3
+ using UnityEngine;
4
+
5
+ namespace TyphoonUnitySDK
6
+ {
7
+ /// <summary>
8
+ /// 朝向
9
+ /// </summary>
10
+ public enum Orientation
11
+ {
12
+ //横屏
13
+ Portrait,
14
+
15
+ //竖屏
16
+ Landscape,
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 7844005f90cef14458bc68bffc3f69bc
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,432 @@
1
+ using System;
2
+ using System.ComponentModel;
3
+ using System.Diagnostics;
4
+ using System.IO;
5
+ using System.Net;
6
+ using System.Net.Http;
7
+ using System.Threading;
8
+ using System.Threading.Tasks;
9
+ using UnityEditor;
10
+ using Debug = UnityEngine.Debug;
11
+
12
+ namespace TyphoonUnitySDK
13
+ {
14
+ /// <summary>
15
+ /// 插件模块安装器
16
+ /// </summary>
17
+ public class PluginModuleInstaller
18
+ {
19
+ //插件名
20
+ public enum PluginNames
21
+ {
22
+ NodeJsV13,
23
+ NodeJsV15,
24
+ Openssl,
25
+ QGToolKit, //快应用工具
26
+ VivoNodeModule, //vivo小游戏Node模块
27
+ }
28
+
29
+ //插件信息
30
+ public class PluginInfo
31
+ {
32
+ public PluginNames PluginName;
33
+ public string Url;
34
+ public string MD5Code;
35
+ public string FolderName; //模块文件名
36
+
37
+ public PluginInfo(PluginNames pluginName, string url, string md5Code, string folderName)
38
+ {
39
+ PluginName = pluginName;
40
+ Url = url;
41
+ MD5Code = md5Code;
42
+ FolderName = folderName;
43
+ }
44
+
45
+ /// <summary>
46
+ /// 模块文件夹
47
+ /// </summary>
48
+ public string RootPath => $"{GetPluginsFolder()}/{FolderName}";
49
+ }
50
+
51
+ // 插件清单
52
+ public static PluginInfo[] PluginsManifest = new PluginInfo[]
53
+ {
54
+ new PluginInfo(PluginNames.NodeJsV13, "https://mecha.nthreecats.com/plugins/node-v10.13.0-win-x64.zip",
55
+ "27f3768a492a3e816cb67cff7f38ff12", "node-v10.13.0-win-x64"),
56
+ new PluginInfo(PluginNames.NodeJsV15, "https://mecha.nthreecats.com/plugins/node-v15.14.0-win-x64.zip",
57
+ "40d03c7c1eed5c6943cc618086adfdf6", "node-v15.14.0-win-x64"),
58
+ new PluginInfo(PluginNames.Openssl, "https://mecha.nthreecats.com/plugins/openssl.zip",
59
+ "bfeb2896c357fdeea87a16ee913e8a65", "openssl"),
60
+ new PluginInfo(PluginNames.QGToolKit, "https://mecha.nthreecats.com/plugins/quickgame-toolkit-unity.zip",
61
+ "a11318f47be10876439a88baf2776b78", ""),
62
+ new PluginInfo(PluginNames.VivoNodeModule, "https://mecha.nthreecats.com/plugins/vivo_node_modules.zip",
63
+ "d945c1bc9473879fc4a2a3f120ca584e", ""),
64
+ };
65
+
66
+ //获取插件信息
67
+ public static PluginInfo GetPluginInfo(PluginNames pluginName)
68
+ {
69
+ foreach (var info in PluginsManifest)
70
+ {
71
+ if (info.PluginName == pluginName)
72
+ {
73
+ return info;
74
+ }
75
+ }
76
+
77
+ throw new Exception($"找不到PluginInfo:{pluginName}");
78
+ }
79
+
80
+
81
+ public static string GetPluginsFolder()
82
+ {
83
+ return $"{UniEditor.GetWindowsUserFolder()}/.typhoonunitysdk/plugins";
84
+ }
85
+
86
+ /// <summary>
87
+ /// 是否安装了NodeV13
88
+ /// </summary>
89
+ public static bool IsInstallNodeV13()
90
+ {
91
+ var root = $"{GetPluginsFolder()}/node-v10.13.0-win-x64";
92
+ var check = new[] { $"{root}/node_modules", $"{root}/node.exe", $"{root}/npm.cmd", };
93
+ return CheckFilesOrDirectoryExists(check);
94
+ }
95
+
96
+ /// <summary>
97
+ /// 安装NodeV13
98
+ /// </summary>
99
+ public static async void InstallNodeV13Async(Action complete = null)
100
+ {
101
+ await InstallModule(PluginNames.NodeJsV13, complete);
102
+ }
103
+
104
+ /// <summary>
105
+ /// 获取插件根目录
106
+ /// </summary>
107
+ public static string GetPluginRootPath(PluginNames plugin)
108
+ {
109
+ return $"{GetPluginsFolder()}/{GetPluginInfo(plugin).FolderName}";
110
+ }
111
+
112
+ /// <summary>
113
+ /// 是否安装openssl
114
+ /// </summary>
115
+ public static bool IsInstallOpenssl()
116
+ {
117
+ var info = GetPluginInfo(PluginNames.Openssl);
118
+ var check = new[] { $"{GetPluginsFolder()}/{info.FolderName}/bin/openssl.exe" };
119
+ return CheckFilesOrDirectoryExists(check);
120
+ }
121
+
122
+ /// <summary>
123
+ /// 安装openssl
124
+ /// </summary>
125
+ public static async void InstallOpensslAsync(Action complete = null)
126
+ {
127
+ await InstallModule(PluginNames.Openssl, complete);
128
+ }
129
+
130
+
131
+ public static async Task InstallModule(PluginNames pluginName, Action complete)
132
+ {
133
+ var pluginInfo = GetPluginInfo(pluginName);
134
+ var url = pluginInfo.Url;
135
+ var fileName = Path.GetFileName(url);
136
+ //判断是否存在安装包
137
+ var zip = $"{UniEditor.GetWindowsUserFolder()}/.typhoonunitysdk/download/{fileName}";
138
+ //创建文件夹
139
+ var folder = Path.GetDirectoryName(zip);
140
+ if (!Directory.Exists(folder))
141
+ {
142
+ Directory.CreateDirectory(folder);
143
+ }
144
+
145
+ if (File.Exists(zip))
146
+ {
147
+ var md5 = MD5Tool.GetMD5HashCodeFromFile(zip);
148
+ if (md5 != pluginInfo.MD5Code)
149
+ {
150
+ Debug.Log($"MD5不匹配,删除{zip}");
151
+ File.Delete(zip);
152
+ }
153
+ }
154
+
155
+ if (!File.Exists(zip))
156
+ {
157
+ var process = 0d;
158
+ var cts = new CancellationTokenSource();
159
+ var task = DownloadFile(url, zip, (p) => { process = p; }, cts.Token);
160
+ var cancel = false;
161
+ while (!task.IsCompleted)
162
+ {
163
+ await Task.Delay(100);
164
+ if (EditorUtility.DisplayCancelableProgressBar($"下载...{fileName}", $"请稍等...{process}%",
165
+ (float)process * 0.01f))
166
+ {
167
+ cancel = true;
168
+ //中断下载
169
+ cts.Cancel();
170
+ //跳出循环
171
+ break;
172
+ }
173
+ }
174
+
175
+ EditorUtility.ClearProgressBar();
176
+ if (cancel)
177
+ {
178
+ Debug.LogError("已取消,安装失败");
179
+ return;
180
+ }
181
+ }
182
+
183
+ if (File.Exists(zip))
184
+ {
185
+ var md5 = MD5Tool.GetMD5HashCodeFromFile(zip);
186
+ if (md5 != pluginInfo.MD5Code)
187
+ {
188
+ File.Delete(zip);
189
+ Debug.LogError($"安装失败,文件MD5不匹配:{zip}");
190
+ return;
191
+ }
192
+ }
193
+
194
+ if (!File.Exists(zip))
195
+ {
196
+ Debug.LogError($"安装失败,找不到:{zip}");
197
+ return;
198
+ }
199
+
200
+ var zipName = Path.GetFileName(zip);
201
+ var step = 0f;
202
+ var unzipTo = GetPluginsFolder();
203
+ ZipTool.UnZip(zip, unzipTo, () =>
204
+ {
205
+ EditorUtility.ClearProgressBar();
206
+ Debug.Log($"安装完毕:{zipName}");
207
+ if (Directory.Exists(pluginInfo.RootPath))
208
+ {
209
+ Explorer(pluginInfo.RootPath);
210
+ }
211
+
212
+ complete?.Invoke();
213
+ },
214
+ (p) =>
215
+ {
216
+ if (p > step)
217
+ {
218
+ step = p + 0.01f;
219
+ EditorUtility.DisplayProgressBar($"解压...{zipName}", $"请稍等...{(p * 100).ToString("F1")}%", p);
220
+ }
221
+ });
222
+ }
223
+
224
+
225
+ public static async Task<bool> DownloadFileAsync(string url, string fileName, Action<double> progress = default,
226
+ CancellationToken cancelationToken = default)
227
+ {
228
+ try
229
+ {
230
+ // 使用HttpClient类创建一个HTTP客户端,指定不使用代理,并设置一个 CookieContainer
231
+ using (var httpClient = new HttpClient(new HttpClientHandler()
232
+ { CookieContainer = new CookieContainer(), UseProxy = false }))
233
+ {
234
+ // 发送GET请求,并等待响应
235
+ var response = await httpClient.GetAsync(new Uri(url),
236
+ HttpCompletionOption.ResponseHeadersRead);
237
+ // 判断请求是否成功,如果失败则返回 false
238
+ if (!response.IsSuccessStatusCode)
239
+ {
240
+ return (false);
241
+ }
242
+
243
+ // 获取响应内容长度
244
+ long contentLength = response.Content.Headers.ContentLength ?? 0;
245
+ // 创建一个文件流,并将响应内容写入文件流
246
+ using (var fs = File.Open(fileName, FileMode.Create,
247
+ FileAccess.ReadWrite, FileShare.Read))
248
+ {
249
+ // 创建一个缓冲区,大小为64KB
250
+ byte[] buffer = new byte[65536];
251
+ // 获取响应流
252
+ var httpStream = await response.Content.ReadAsStreamAsync();
253
+ // 定义变量,用于记录每次读取的字节数
254
+ int readLength = 0;
255
+ // 循环异步读取响应流的内容,直到读取完毕
256
+ while ((readLength = await httpStream.ReadAsync(buffer, 0, buffer.Length, cancelationToken)) >
257
+ 0)
258
+ {
259
+ // 检查是否已经取消了任务
260
+ if (cancelationToken.IsCancellationRequested)
261
+ {
262
+ // 如果任务已经取消,关闭文件流,并删除已经下载的文件
263
+ fs.Close();
264
+ File.Delete(fileName);
265
+ return (false);
266
+ }
267
+
268
+ // 将读取到的内容写入文件流,并调用进度回调函数
269
+ await fs.WriteAsync(buffer, 0, readLength, cancelationToken);
270
+ progress?.Invoke(Math.Round((double)fs.Length / contentLength * 100, 2));
271
+ }
272
+ }
273
+ }
274
+
275
+ // 返回true表示文件下载成功
276
+ return (true);
277
+ }
278
+ catch (Exception e)
279
+ {
280
+ Debug.LogError($"下载失败:{e}");
281
+ // 返回false表示文件下载失败
282
+ return (false);
283
+ }
284
+ }
285
+
286
+ /// <summary>
287
+ /// 下载安装包到本地
288
+ /// </summary>
289
+ private static async Task DownloadAsync(string url, string filePath, Action<int> onProgress,
290
+ CancellationToken cancelationToken = default)
291
+ {
292
+ using (HttpClient client = new HttpClient(new HttpClientHandler()
293
+ { CookieContainer = new CookieContainer(), UseProxy = false }))
294
+ {
295
+ try
296
+ {
297
+ HttpResponseMessage
298
+ response = await client.GetAsync(url,
299
+ HttpCompletionOption.ResponseHeadersRead); // 使用ResponseHeadersRead选项获取响应头
300
+
301
+ if (response.IsSuccessStatusCode)
302
+ {
303
+ long totalLength = response.Content.Headers.ContentLength ?? -1; // 获取文件总长度(如果可用)
304
+ using (var stream = await response.Content.ReadAsStreamAsync()) // 异步读取响应流
305
+ {
306
+ using (var fileStream =
307
+ new FileStream(filePath, FileMode.Create, FileAccess.Write)) // 创建文件流
308
+ {
309
+ byte[] buffer = new byte[4096]; // 缓冲区大小
310
+ long downloadedBytes = 0; // 已下载字节数
311
+
312
+ int bytesRead;
313
+ while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
314
+ {
315
+ await fileStream.WriteAsync(buffer, 0, bytesRead); // 将数据写入文件
316
+
317
+ downloadedBytes += bytesRead;
318
+ double progress = (double)downloadedBytes / totalLength * 100; // 计算下载进度
319
+ onProgress?.Invoke((int)progress); // 调用进度回调
320
+
321
+ // 继续处理已下载的数据...
322
+ if (cancelationToken.IsCancellationRequested)
323
+ {
324
+ // 如果任务已经取消,关闭文件流,并删除已经下载的文件
325
+ fileStream.Close();
326
+ File.Delete(filePath);
327
+ break;
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ if (cancelationToken.IsCancellationRequested)
334
+ {
335
+ Debug.LogError("取消下载");
336
+ }
337
+ else
338
+ {
339
+ Debug.Log("下载完成");
340
+ }
341
+ }
342
+ else
343
+ {
344
+ Debug.LogError("下载失败:" + response.StatusCode);
345
+ }
346
+ }
347
+ catch (Exception ex)
348
+ {
349
+ Debug.LogError("下载出错:" + ex.Message);
350
+ }
351
+ }
352
+ }
353
+
354
+
355
+ protected static async Task DownloadFile(string url, string savePath, Action<int> onProgress,
356
+ CancellationToken cancelationToken = default)
357
+ {
358
+ using (WebClient webClient = new WebClient())
359
+ {
360
+ webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(
361
+ delegate(object sender, DownloadProgressChangedEventArgs e)
362
+ {
363
+ try
364
+ {
365
+ onProgress?.Invoke(e.ProgressPercentage);
366
+ }
367
+ catch (Exception exception)
368
+ {
369
+ }
370
+
371
+ if (cancelationToken.IsCancellationRequested)
372
+ {
373
+ webClient.CancelAsync();
374
+ }
375
+ });
376
+
377
+ webClient.DownloadFileCompleted += new AsyncCompletedEventHandler
378
+ (delegate(object sender, AsyncCompletedEventArgs e)
379
+ {
380
+ if (e.Error == null && !e.Cancelled)
381
+ {
382
+ try
383
+ {
384
+ if (File.Exists(savePath))
385
+ {
386
+ Debug.Log("下载成功!");
387
+ }
388
+ }
389
+ catch (Exception exception)
390
+ {
391
+ Debug.LogError($"下载失败:{exception}");
392
+ }
393
+ }
394
+
395
+ if (e.Cancelled)
396
+ {
397
+ Debug.LogError($"取消下载");
398
+ if (File.Exists(savePath))
399
+ {
400
+ File.Delete(savePath);
401
+ }
402
+ }
403
+ });
404
+ await webClient.DownloadFileTaskAsync(new Uri(url), savePath);
405
+ }
406
+ }
407
+
408
+ //检查清单
409
+ public static bool CheckFilesOrDirectoryExists(params string[] path)
410
+ {
411
+ foreach (var element in path)
412
+ {
413
+ if (!File.Exists(element) && !Directory.Exists(element))
414
+ {
415
+ return false;
416
+ }
417
+ }
418
+
419
+ return true;
420
+ }
421
+
422
+ //预览文件夹或文件
423
+ private static void Explorer(string path)
424
+ {
425
+ var fullPath = Path.GetFullPath(path);
426
+ Debug.Log(fullPath);
427
+ using (Process.Start($"explorer", $"\"{fullPath}\""))
428
+ {
429
+ }
430
+ }
431
+ }
432
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 1123b1a840bc77248b126c470a9b8eb0
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: