Compare commits

...

830 Commits

Author SHA1 Message Date
何冠峰
d712a00458 Update .gitignore 2026-05-09 17:06:55 +08:00
何冠峰
c14244b2cf Update copyright year for TuYoo Games 2026-04-21 10:15:21 +08:00
何冠峰
4b6a8ca406 Update CHANGELOG.md 2025-12-04 18:30:51 +08:00
何冠峰
c8e45a6cae Update package.json 2025-12-04 18:30:46 +08:00
何冠峰
1fbc9d26a6 style : 修改注释说明 2025-12-04 18:16:40 +08:00
何冠峰
abb087b02e fix #700 2025-12-03 10:14:55 +08:00
何冠峰
aeaf03011f Merge pull request #694 from fslse/ClearBundleFilesByLocations
ClearBundleFilesByLocations
2025-11-22 09:39:21 +08:00
DESKTOP-FIVME83\Administrator
78d24ad3a6 清理指定地址的文件
(cherry picked from commit 41a1973be8f11c1629b334238546556f54101c35)
2025-11-21 16:29:21 +08:00
何冠峰
aab2c4625e feat #671 2025-11-13 15:54:08 +08:00
何冠峰
079ef75605 feat #682 2025-11-13 11:51:28 +08:00
何冠峰
75881b55f6 fix #683 2025-11-12 18:41:17 +08:00
何冠峰
2020c7d508 Merge pull request #687 from OpenLBE/dev
Localize UI strings to English in editor windows
2025-11-12 09:58:46 +08:00
lark
088d939346 Localize UI strings to English in editor windows
Replaced Chinese UI strings with English equivalents in various editor windows and dialogs, including AssetArtReporter, AssetArtScanner, and AssetBundleBuilder viewers. This improves accessibility for non-Chinese users and standardizes the language across the editor tools.
2025-11-11 14:43:49 +08:00
何冠峰
fa50e91c9f fix #684 2025-11-07 16:37:26 +08:00
何冠峰
2e7b992a4b Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-11-07 16:23:54 +08:00
何冠峰
29fbbd97ff fix #678 2025-11-07 16:23:51 +08:00
何冠峰
abb150e33f Merge pull request #676 from coffeeofnosugar/dev
修复UniTask的扩展包问题
2025-11-04 15:59:20 +08:00
coffee
78e20f434e 修复UniTask的扩展包问题
Unity版本: 2021.3.45f1
yooasset版本:2.3.17
少了一个下划线
2025-11-01 23:24:03 +08:00
何冠峰
304222b788 Update EditorDefine.cs 2025-10-31 17:03:27 +08:00
何冠峰
101236db8a Update CHANGELOG.md 2025-10-30 20:49:54 +08:00
何冠峰
37de007b3f Update package.json 2025-10-30 20:49:51 +08:00
何冠峰
d570ba8d74 fix #661 2025-10-30 18:31:06 +08:00
何冠峰
2a956099ae 移除程序集里冗余引用 2025-10-30 11:25:21 +08:00
何冠峰
74037a5a29 fix #670 2025-10-28 19:16:51 +08:00
何冠峰
861f850a32 Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-10-27 17:42:32 +08:00
何冠峰
8b1b5f988a fix #669 2025-10-27 17:42:29 +08:00
何冠峰
efafd1173f Merge pull request #667 from yueh0607/fix/chinese-input-textfield
Fix Chinese input issue in TextField by enabling isDelayed
2025-10-27 09:50:52 +08:00
yzp
03e49ff1fb Fix Chinese input issue in TextField by enabling isDelayed
Fixed an issue where Chinese IME candidate characters were being incorrectly inserted into TextFields (PackageDesc, GroupDesc, etc.), causing garbled text like "默认包baobabmo'rmom".

The fix sets `isDelayed = true` on all TextFields in AssetBundleCollectorWindow, which defers value change callbacks until the user completes input (by pressing Enter or losing focus), thus avoiding interference from IME candidate characters.

Modified TextFields:
- PackageName
- PackageDesc
- GroupName
- GroupDesc
- GroupTags
- User Data (collector)
- Asset Tags (collector)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 00:01:48 +08:00
何冠峰
ea34be1f00 fix #646 2025-10-15 17:27:08 +08:00
何冠峰
831a9981e3 Update SearchCacheFilesOperation.cs 2025-10-14 16:58:06 +08:00
何冠峰
9de4aaa658 Merge pull request #656 from AlanLiu90/dev
优化SearchCacheFilesOperation
2025-10-14 16:43:07 +08:00
Alan Liu
3579a23bd5 优化SearchCacheFilesOperation 2025-10-13 18:55:49 +08:00
何冠峰
c865ddc7f2 feat #650 2025-10-10 10:20:02 +08:00
何冠峰
0bde506aec feat #648 2025-10-09 19:10:26 +08:00
何冠峰
15005b3d30 sample : 程序集宏支持
YOO_MACRO_SUPPORT开启扩展代码
2025-10-09 19:07:03 +08:00
何冠峰
4caf733ac6 fix #652 2025-10-09 16:17:44 +08:00
何冠峰
014b17f5cb feat #643 2025-10-09 16:14:31 +08:00
何冠峰
f3ebda0c04 refactor : 重构资源清单反序列化逻辑 2025-09-30 15:35:32 +08:00
何冠峰
5602addaca fix #645
修复极端情况下Shader变种收集不完整的问题
2025-09-24 16:37:46 +08:00
何冠峰
c4ae67aa8e perf: 资源扫描不再主动生成报告文件 2025-09-23 11:08:55 +08:00
何冠峰
bbcc3bf971 style : 修改代码注释说明 2025-09-19 10:05:45 +08:00
何冠峰
8b0e75b9b3 feat : 扩展Taptap小游戏文件类 2025-09-19 10:05:16 +08:00
何冠峰
b1f02049cc Update CHANGELOG.md 2025-09-17 16:59:24 +08:00
何冠峰
512886cdf6 Update package.json 2025-09-17 16:58:59 +08:00
何冠峰
0c3ccc5c2f refactor: 适配引擎版本 2025-09-17 16:49:21 +08:00
何冠峰
b0ea03170f refactor : 移除下载器的timeout参数
可以使用看门狗机制代替。
2025-09-17 15:53:22 +08:00
何冠峰
2c3b890329 feat #642 2025-09-17 15:39:47 +08:00
何冠峰
0f39cb9444 update space shooter 2025-09-17 10:53:56 +08:00
何冠峰
8acc16d3f6 perf #632 2025-09-17 10:53:40 +08:00
何冠峰
fd1715a89b fix 修正无效警告 2025-09-17 10:51:24 +08:00
何冠峰
0934c813d1 fix #644 2025-09-13 18:18:31 +08:00
何冠峰
be71d38cd8 update AssetBundleBuilder 2025-09-11 19:20:16 +08:00
何冠峰
4cdfde31da update AssetArtScanner 2025-09-11 19:19:55 +08:00
何冠峰
0133549ef8 feat #638
修复问题,防止游离的Bundle加载任务出现。
2025-09-11 14:03:42 +08:00
何冠峰
81d9eb47c8 feat #638 2025-09-11 11:07:13 +08:00
何冠峰
5fde689f1f feat #640 2025-09-10 21:19:58 +08:00
何冠峰
5d51bfe751 feat #639
修复问题
2025-09-10 21:00:51 +08:00
何冠峰
ed86edd2b0 feat #639 2025-09-10 20:15:52 +08:00
何冠峰
f627b5b59a Update CHANGELOG.md 2025-09-10 12:05:31 +08:00
何冠峰
549ec74519 Update CHANGELOG.md 2025-09-09 20:06:53 +08:00
何冠峰
247ee31348 Update package.json 2025-09-09 20:06:31 +08:00
何冠峰
90d3a53bc3 fix #631 2025-09-09 19:06:17 +08:00
何冠峰
19f1d67a61 feat : 弱引用资源句柄 2025-09-09 18:31:02 +08:00
何冠峰
a71c46d1c4 feat : 构建过程图集依赖计算增加开关 2025-09-08 19:00:55 +08:00
何冠峰
82d7bc8fef fix #614 增加Taptap小游戏扩展类 2025-08-30 18:09:28 +08:00
何冠峰
cc85099253 update mini game
重构相关代码,使用通用逻辑
2025-08-30 17:38:26 +08:00
何冠峰
d392b02bd4 refactor : 重构了Web文件系统公共类
方便小游戏共用基础代码。
2025-08-30 17:30:29 +08:00
何冠峰
a5138b9846 feat : 在SBP构建管线里,自动建立主资源对象对图集的依赖关系 2025-08-29 19:06:55 +08:00
何冠峰
e1b6458c26 update space shooter 2025-08-29 19:04:29 +08:00
何冠峰
0f73dc3047 update sample 2025-08-28 22:08:02 +08:00
何冠峰
a85e49c22a fix #625 2025-08-28 22:07:00 +08:00
何冠峰
6b291de922 fix #617 2025-08-28 19:02:08 +08:00
何冠峰
a4b1300195 fix #623 2025-08-28 10:40:13 +08:00
何冠峰
6f34951a74 refactor #627 2025-08-28 10:27:37 +08:00
何冠峰
c798250258 feat : CRC工具类增加获取整形值的方法 2025-08-27 19:19:00 +08:00
何冠峰
6fc82bb55a feat : 新增配置参数控制缓存文件验证最大并发数 2025-08-27 18:03:53 +08:00
何冠峰
c22cf5ffeb fix #620 2025-08-27 16:04:18 +08:00
何冠峰
36bc24f9fd fix #622 2025-08-27 10:29:13 +08:00
何冠峰
addb0ecdfe build #621 2025-08-27 10:27:12 +08:00
何冠峰
89e23e0df8 perf : 优化异步操作系统的繁忙检测机制
默认情况下不必检测
2025-08-16 16:53:28 +08:00
何冠峰
e2f582834e fix #611 2025-08-13 10:29:41 +08:00
何冠峰
d2c2844f61 update mini game
移除冗余代码
2025-08-13 10:29:25 +08:00
何冠峰
1de64278ad sample : 新增生成内置清单文件的页面工具 2025-08-04 18:36:43 +08:00
何冠峰
227f2332a9 refactor : 重构内置文件的加载和拷贝逻辑。
优先使用File类拷贝文件
2025-08-04 17:26:57 +08:00
何冠峰
131614687c Update LICENSE 2025-07-30 14:18:26 +08:00
何冠峰
b8ec902f60 perf : IsUnpackBundleFile方法设置为虚方法 2025-07-29 14:34:59 +08:00
何冠峰
eb3e29b6ad style : 修改形参注释 2025-07-29 14:33:54 +08:00
何冠峰
11ed9d391a build : 预留构建Mono脚本资源包方法。 2025-07-25 16:09:29 +08:00
何冠峰
9cd50bc7f3 fix : 修复构建页面扩展类缺少指定属性报错的问题。 2025-07-25 15:43:37 +08:00
何冠峰
e92505ba88 samples : 增加自定义构建页面的扩展示例 2025-07-25 15:42:17 +08:00
何冠峰
06a670730c Update README.md 2025-07-25 14:50:13 +08:00
何冠峰
ccd21e56cb sample : 更新UniTask扩展库的说明文档 2025-07-24 16:35:22 +08:00
何冠峰
522bcc529a update UniTask sample 2025-07-24 14:56:58 +08:00
何冠峰
2254ac9f5e update UniTask sample
更新说明文档
2025-07-24 14:45:52 +08:00
何冠峰
956b3db71d Merge pull request #601 from GodChouyu/dev
UniTask示例删除UniTask源码,修改为扩展支持。
2025-07-24 11:31:33 +08:00
何冠峰
fb56959c61 style : 统一小游戏编码规范和命名规范 2025-07-24 11:21:37 +08:00
何冠峰
b9b9f4e37d feat : 新增支付宝小游戏文件系统扩展类 2025-07-24 11:18:29 +08:00
GodChouyu
c050d6d172 UniTask示例删除UniTask源码,修改为扩展支持。 2025-07-24 10:15:17 +08:00
何冠峰
baf76a454b Update CHANGELOG.md 2025-07-23 18:49:13 +08:00
何冠峰
385d343262 Update package.json 2025-07-23 18:49:02 +08:00
何冠峰
1f5ad24d44 test : 完善测试用例代码 2025-07-23 18:46:54 +08:00
何冠峰
fefc0043cf fix : 修正小游戏脚本编译错误 2025-07-23 18:46:12 +08:00
何冠峰
f49143d4f7 Update CHANGELOG.md 2025-07-23 17:12:19 +08:00
何冠峰
fd760b12a3 Update package.json 2025-07-23 17:12:05 +08:00
何冠峰
14cf8e9ca3 update space shooter 2025-07-23 17:11:49 +08:00
何冠峰
3595219a71 style : 移除冗余空格 2025-07-23 16:48:37 +08:00
何冠峰
a4c7d4b8f5 test : 修改资源清单加密解密测试用例 2025-07-23 15:41:57 +08:00
何冠峰
43c5c7fb53 feat : 增加构建前置处理扩展示例
内置清单构建
2025-07-23 15:41:00 +08:00
何冠峰
48d2b36d4e feat : 改进资源清单加密和解密接口 2025-07-23 15:38:29 +08:00
何冠峰
2fd87f4d4b test : 新增测试用例 2025-07-23 14:08:26 +08:00
何冠峰
0fd75b835a style : 修正参数命名 2025-07-23 14:07:12 +08:00
何冠峰
4489ca570b style : 修改日志 2025-07-23 14:06:32 +08:00
何冠峰
268792b576 fix #592
优化不必要的GC
2025-07-23 11:07:29 +08:00
何冠峰
33907ea967 fix #591
新增DISABLE_ONDEMAND_DOWNLOAD文件配置参数
2025-07-22 18:59:47 +08:00
何冠峰
5d7afff3e4 update mini game
增加单元测试用例
2025-07-22 17:40:39 +08:00
何冠峰
fa15f83d85 Update UnityWebCacheRequestOperation.cs 2025-07-22 17:36:39 +08:00
何冠峰
1801974c8a Update DownloadCenterOperation.cs 2025-07-22 10:11:22 +08:00
何冠峰
bfd476d59c Update DownloadCenterOperation.cs 2025-07-21 18:22:51 +08:00
何冠峰
7dd08e9634 update test sample 2025-07-21 18:05:08 +08:00
何冠峰
b2776b933a update mini game sample 2025-07-21 15:52:51 +08:00
何冠峰
9f09b6c526 update file system 2025-07-21 15:52:07 +08:00
何冠峰
01f6103b48 Update AssemblyInfo.cs 2025-07-21 15:48:52 +08:00
何冠峰
053b4a00d7 update test sample 2025-07-17 22:24:27 +08:00
何冠峰
db159428c6 update test sample
增加cache file system单元测试
2025-07-17 21:26:13 +08:00
何冠峰
ac7ee16017 update mini game 2025-07-17 21:23:34 +08:00
何冠峰
c2fb7c3cbb update package invoke
correct name
2025-07-17 21:09:35 +08:00
何冠峰
e70b0d37cd update extension sample 2025-07-17 21:00:46 +08:00
何冠峰
53db012fc8 update download system 2025-07-17 21:00:12 +08:00
何冠峰
b3622167da update download system
remove timeout
2025-07-17 20:59:15 +08:00
何冠峰
dd6fab46f9 update extension sample 2025-07-16 10:48:40 +08:00
何冠峰
f0796dccc9 Update GooglePlayFileSystem.cs 2025-07-10 22:50:43 +08:00
何冠峰
f383c59327 update mini game sample
新增Google Play文件系统扩展
2025-07-10 22:43:43 +08:00
何冠峰
e34b9270d2 update mini game
下载器相关代码重构
2025-07-10 10:58:44 +08:00
何冠峰
b90ab01fe9 update file system
下载器相关逻辑代码重构
2025-07-10 10:58:14 +08:00
何冠峰
236468b4a8 update download system
重构下载逻辑代码
2025-07-09 14:52:22 +08:00
何冠峰
6f5fcd55b1 style : 修正拼写错误 2025-07-08 16:42:21 +08:00
何冠峰
4b8f2e3acc update download system
重构下载逻辑代码
2025-07-08 16:41:50 +08:00
何冠峰
090e4f4b15 fix #590 2025-07-01 18:10:17 +08:00
何冠峰
53163a75ae Update CHANGELOG.md 2025-07-01 16:46:10 +08:00
何冠峰
273401cb20 Update package.json 2025-07-01 16:45:50 +08:00
何冠峰
97fe3b0681 update file system
修正2.3.11版本同步加载本地加密文件失败的问题。
2025-07-01 16:40:01 +08:00
何冠峰
d401086fd1 update test sample 2025-07-01 15:32:44 +08:00
何冠峰
e3a12ef361 style : file system code style 2025-07-01 11:06:41 +08:00
何冠峰
1b0288fcd0 update mini game
微信小游戏和抖音小游戏支持资源清单加密。
2025-06-30 16:19:59 +08:00
何冠峰
3ee94fb3b9 update extension sample 2025-06-30 15:43:47 +08:00
何冠峰
a0ea80c158 Update CHANGELOG.md 2025-06-30 12:06:30 +08:00
何冠峰
264415b362 Update package.json 2025-06-30 12:06:07 +08:00
何冠峰
6a76d44c38 update test sample 2025-06-30 11:30:56 +08:00
何冠峰
cebfd57851 update test sample 2025-06-30 11:22:38 +08:00
何冠峰
60eb1c3522 update test sample
修正单元测试失败
2025-06-30 11:07:46 +08:00
何冠峰
40c82835bf style : code style 2025-06-30 10:53:16 +08:00
何冠峰
a13913f572 Merge pull request #582 from hhmmLife/dev
fix: 只有递归收集依赖时,依赖列表中才默认包含主资源
2025-06-30 10:47:28 +08:00
何冠峰
150b46a0a7 update file system
新增ICopyLocalFileServices服务类
2025-06-27 17:42:57 +08:00
何冠峰
ebde5a52d3 fix #585 2025-06-25 19:27:52 +08:00
何冠峰
e57466e9e2 style : file system code 2025-06-25 18:12:37 +08:00
何冠峰
6f7fca7b34 perf : main thread sleep one 2025-06-25 18:10:50 +08:00
何冠峰
756331fe0b style : file system code 2025-06-25 18:04:53 +08:00
何冠峰
5139e2f3a7 update extension sample 2025-06-23 18:57:48 +08:00
hhmmLife
1c4aba6db5 fix: 只有递归收集依赖时,依赖列表中才默认包含主资源 2025-06-23 00:56:50 +08:00
何冠峰
44faa0c5e6 fix #572
修复了资源收集页面指定收集的预制体名称变动的问题。
2025-06-20 17:55:51 +08:00
何冠峰
72c97341b1 fix #579 2025-06-20 14:03:12 +08:00
何冠峰
9acc240b5a update extension sample 2025-06-20 11:36:56 +08:00
何冠峰
ed89e73d26 fix #576
资源清单加密和解密
2025-06-20 11:36:29 +08:00
何冠峰
9e33df0375 style :services code 2025-06-20 11:29:22 +08:00
何冠峰
6c98f9a09d update resource manager
新增初始化参数:WebGLForceSyncLoadAsset
2025-06-18 11:12:42 +08:00
何冠峰
9ed85afb29 Update CHANGELOG.md 2025-06-17 19:26:39 +08:00
何冠峰
560a395173 Update CHANGELOG.md 2025-06-17 19:23:57 +08:00
何冠峰
8bce963588 Update package.json 2025-06-17 19:23:32 +08:00
何冠峰
f8a3fe47e5 add mini game sample
修复程序集不正确的问题
2025-06-17 18:29:17 +08:00
何冠峰
48356a4f9e fix #573 2025-06-17 18:20:28 +08:00
何冠峰
d2a28bd801 fix #562 2025-06-17 17:07:02 +08:00
何冠峰
3949abb53f fix #566
重构了资源构建页面,方便扩展自定义界面。
2025-06-17 15:29:54 +08:00
何冠峰
06a50a049e add mini game sample 2025-06-13 18:31:05 +08:00
何冠峰
6f049e2427 add mini game sample
小游戏扩展库独立
2025-06-13 18:19:35 +08:00
何冠峰
01c08a46ab fix #564 2025-06-13 17:39:30 +08:00
何冠峰
31dc5b494d fix #569 2025-06-13 17:25:13 +08:00
何冠峰
18e74e906e fix #551 2025-06-13 17:18:38 +08:00
何冠峰
4f62b249b4 update TableView
增加AssetObjectCell类
2025-05-19 16:25:16 +08:00
何冠峰
fe7f9bff08 fix #552 2025-05-15 15:38:13 +08:00
何冠峰
e71077f294 fix space shooter quit game error
修复太空战机DEMO在退出运行模式时的报错。
2025-05-13 17:53:17 +08:00
何冠峰
eabebf3d8f Update CHANGELOG.md 2025-05-13 10:47:59 +08:00
何冠峰
4ef789520a Update package.json 2025-05-13 10:47:49 +08:00
何冠峰
4322f3c58c fix #545 2025-05-13 10:23:22 +08:00
何冠峰
c40a796170 fix #542 2025-05-13 10:11:06 +08:00
何冠峰
32841d4773 Update AssetBundleDebuggerWindow.cs 2025-05-09 15:29:26 +08:00
何冠峰
e469b32d94 refactor: The tag diffusion logic in the collector
优化收集器tag传染扩散逻辑,避免Group里配置了Tag导致的无意义的警告信息。
2025-04-23 18:42:26 +08:00
何冠峰
c0e5315953 feat : Buld the pipeline output the log file.
构建管线输出构建日志到输出目录下。
2025-04-23 18:19:13 +08:00
何冠峰
7b5f366533 Build system add BuiltinShadersBundleNameIsNull ErrorCode 2025-04-23 16:56:03 +08:00
何冠峰
e674d5bf97 update extension sample
PanelMonitor增加控制开关
2025-04-23 16:39:07 +08:00
何冠峰
9b0bebd981 refactor : Macro scripts control by YOO_ASSET_EXPERIMENT 2025-04-23 16:38:17 +08:00
何冠峰
dc46462bfa fix : remove Caching class
it's not support in webGL
2025-04-23 14:14:34 +08:00
何冠峰
51c9943cf2 修复了输出csproject工程文件编码为UTF16的问题
修正BOM问题
2025-04-22 17:41:36 +08:00
何冠峰
3db9b750e3 update logo 2025-04-22 16:47:44 +08:00
何冠峰
1b57a0b7df 修复了输出csproject工程文件编码为UTF16的问题。 2025-04-22 16:47:33 +08:00
何冠峰
bd5ce1e6bd perf : webgl platform use crc verify the bundle when first time downloaded
WebGL平台首次下载会验证CRC。
2025-04-18 18:21:24 +08:00
何冠峰
7eb74d4dd1 update extension sample 2025-04-18 17:11:40 +08:00
何冠峰
a384ca1f18 feat : scriptable build pipeline add StripUnityVersion parameter.
新增构建参数
2025-04-18 16:48:03 +08:00
何冠峰
c7253a3f23 Update CHANGELOG.md 2025-04-17 19:02:59 +08:00
何冠峰
b296abb27e Update package.json 2025-04-17 19:02:57 +08:00
何冠峰
999ede6bab fix #534 2025-04-17 18:51:08 +08:00
何冠峰
bd1569c34d fix #533 2025-04-17 18:47:59 +08:00
何冠峰
3c265c1ab4 update extension sample 2025-04-17 15:38:07 +08:00
何冠峰
570a3a817c update space shooter 2025-04-17 15:16:05 +08:00
何冠峰
7a8f344927 update extension sample 2025-04-17 15:15:48 +08:00
何冠峰
b2c9cb3a7e update space shooter 2025-04-17 14:16:56 +08:00
何冠峰
06a5c90b23 update space shooter 2025-04-17 12:00:45 +08:00
何冠峰
dcd8ced42a update space shooter 2025-04-17 11:10:08 +08:00
何冠峰
76b31bd3cf update extension sample 2025-04-17 11:09:37 +08:00
何冠峰
009e8ece79 fix #528 #531 2025-04-15 14:20:32 +08:00
何冠峰
4e257ab27d fix #531 2025-04-09 11:39:42 +08:00
何冠峰
927400b669 refactor : EFileNameStyle move to runtime code 2025-04-08 14:28:52 +08:00
何冠峰
c0d42e79d8 refactor : DownloadParam rename DownloadFileOptions 2025-04-08 11:48:32 +08:00
何冠峰
b843c6b0ed refactor : add ClearCacheFilesOptions define 2025-04-08 11:34:46 +08:00
何冠峰
9fb7f8bbfe Update CHANGELOG.md 2025-04-01 14:20:52 +08:00
何冠峰
b0382afad0 Update package.json 2025-04-01 14:20:46 +08:00
何冠峰
1ab7689174 fix #524
新增初始化参数 BundleLoadingMaxConcurrency
2025-04-01 11:44:10 +08:00
何冠峰
29d456c065 fix #523 2025-04-01 10:22:01 +08:00
何冠峰
b0dc829b04 fix #515
资源路径大小写不敏感逻辑优化
2025-03-31 19:06:03 +08:00
何冠峰
b3ead90832 fix #526 2025-03-31 18:13:07 +08:00
何冠峰
7bf00d4ff6 update space shooter 2025-03-31 17:28:10 +08:00
何冠峰
030e94d8ff update test sample 2025-03-31 17:27:58 +08:00
何冠峰
cf05254121 fix #519
FileSystemParametersDefine新增参数:INSTALL_CLEAR_MODE
2025-03-31 17:26:46 +08:00
何冠峰
3f786bca3b Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-03-26 15:12:04 +08:00
何冠峰
98719d212f Merge pull request #520 from SongQQQ/fix-UWPError
修复了UWP平台报错
2025-03-26 14:35:24 +08:00
SONG\11700
3409f7ce4d 修复了UWP平台报错 2025-03-26 12:07:59 +08:00
何冠峰
f57b354e9b fix : UWP平台的适配问题。
修复UWP平台获取WWW加载路径未适配的问题。
2025-03-26 11:45:50 +08:00
何冠峰
974493f88d Update CHANGELOG.md 2025-03-25 11:15:56 +08:00
何冠峰
69a69988a1 Update package.json 2025-03-25 11:15:24 +08:00
何冠峰
4e9c1955eb fix #486 2025-03-14 18:54:03 +08:00
何冠峰
b6c68a533e update asset bundle builder
增加TaskCreateCatalog任务节点
2025-03-14 18:49:56 +08:00
何冠峰
38aa1c3509 update file system 2025-03-14 18:26:04 +08:00
何冠峰
eb2f783417 update resource package 2025-03-14 17:23:55 +08:00
何冠峰
8556e071fa fix #507 2025-03-14 16:50:48 +08:00
何冠峰
6155256fb6 Update CHANGELOG.md 2025-03-14 14:48:16 +08:00
何冠峰
0d4f2bc893 Update package.json 2025-03-14 14:47:39 +08:00
何冠峰
600e928ab4 fix #512 2025-03-14 14:32:39 +08:00
何冠峰
4599ff098c update resource package
优化ClearCacheFilesAsync方法
2025-03-14 12:27:01 +08:00
何冠峰
4d2df5b705 Update TestBundleEncryption.cs 2025-03-13 16:29:48 +08:00
何冠峰
79a7732cfd Update InitializeParameters.cs 2025-03-13 14:00:59 +08:00
何冠峰
79467bbf13 update editor assembly 2025-03-12 18:32:28 +08:00
何冠峰
c7d678282b Merge pull request #501 from Y-way/support-macros
Update MacrosProcessor.cs
2025-03-12 17:17:47 +08:00
何冠峰
d376afc217 fix #508 2025-03-12 17:16:24 +08:00
何冠峰
a62f808591 fix #506 2025-03-12 16:36:37 +08:00
何冠峰
b334a4986b fix #504 2025-03-12 10:39:44 +08:00
何冠峰
a4111349a0 fix #502 2025-03-11 15:40:57 +08:00
Y-way
bdcf95384f Update .gitignore 2025-03-10 16:13:18 +08:00
Y-way
d910af589d Update MacrosProcessor.cs
修正YooAsset相关宏在引用库不能生效的问题.
2025-03-10 15:22:44 +08:00
何冠峰
0531864534 Update package.json 2025-03-10 10:29:44 +08:00
何冠峰
72b1278f5c Merge pull request #499 from benjamini258369gmail/fix-rawIgnore-dll
fix ignore raw dll
2025-03-10 10:27:13 +08:00
benjamini
875cd24cba fix ignore raw dll 2025-03-08 17:54:11 +09:00
何冠峰
fcc729a0bf Update CHANGELOG.md 2025-03-08 15:53:46 +08:00
何冠峰
d10e54248b Update package.json 2025-03-08 15:53:35 +08:00
何冠峰
b84800a905 update assembly 2025-03-08 15:51:27 +08:00
何冠峰
8ccd7e552c fix #498 2025-03-08 15:41:03 +08:00
何冠峰
772ba484eb Update HandleFactory.cs 2025-03-08 15:01:19 +08:00
何冠峰
cdbedee705 update asmdef
YooAsset版本宏定义
2025-03-08 14:34:41 +08:00
何冠峰
10cce48e71 Merge pull request #497 from Y-way/support-macros
Support DefineConstants for YooAsset Package
2025-03-08 12:05:07 +08:00
何冠峰
13e8410d80 fix #389 2025-03-08 11:50:35 +08:00
何冠峰
6f07faf4da fix #495 2025-03-08 11:24:17 +08:00
何冠峰
e3228d406e update resource manager
优化Handle生成和移除逻辑
2025-03-08 10:58:19 +08:00
何冠峰
daf2133535 fix #496 2025-03-07 15:03:13 +08:00
Y-way
9bcbc10862 Support DefineConstants for YooAsset Package
自定义YOO_VERSION_2  以及版本管理宏,用于YooAsset升级时的宏定义处理
2025-03-07 15:00:20 +08:00
何冠峰
e6958d205e Update CHANGELOG.md 2025-03-06 15:05:52 +08:00
何冠峰
b03d9db2b0 Update package.json 2025-03-06 15:05:39 +08:00
何冠峰
30853b6d62 update space shooter 2025-03-06 14:31:40 +08:00
何冠峰
a7cafcb328 update UIElements
展示单位Units
2025-03-06 14:31:26 +08:00
何冠峰
d03bca5512 update asset bundle debugger 2025-03-06 12:20:45 +08:00
何冠峰
af3fc50188 update UIElements 2025-03-06 12:20:13 +08:00
何冠峰
b71eeeb855 update UIElements 2025-03-06 11:45:51 +08:00
何冠峰
317c42521a update test sample 2025-03-06 11:39:26 +08:00
何冠峰
064d69269e Update PakcageInvokeBuildParam.cs 2025-03-06 11:17:20 +08:00
何冠峰
9e6401d3c0 update space shooter 2025-03-06 11:17:00 +08:00
何冠峰
2aaba328ee fix #488 2025-03-06 11:16:21 +08:00
何冠峰
62fdc93a82 update test sample 2025-03-06 10:55:54 +08:00
何冠峰
408f0942ee update test sample 2025-03-05 20:00:02 +08:00
何冠峰
ddda9e29db fix #491 2025-03-05 17:39:33 +08:00
何冠峰
c2b33f5ec4 fix #492 2025-03-05 17:29:52 +08:00
何冠峰
e58999e484 update asset bundle debugger 2025-03-05 17:26:58 +08:00
何冠峰
ed9692574c Update AssetBundleSimulateBuilder.cs
模拟构建默认启用依赖关系数据库
2025-03-05 10:54:33 +08:00
何冠峰
f7e078e064 update file system 2025-03-05 10:54:02 +08:00
何冠峰
b74a44dc36 update UIElements 2025-03-03 20:57:50 +08:00
何冠峰
6b36cdb5ee update AssetBundleDebugger
内置了新的UIElments的TreeViewer组件。
2025-03-03 18:28:02 +08:00
何冠峰
56ae1a8f95 update UIElements 2025-02-28 19:06:17 +08:00
何冠峰
3069b1d1f1 update diagnostic system 2025-02-28 18:38:18 +08:00
何冠峰
e7d346e4e1 update diagnostic system
调试窗口增加异步操作视图
2025-02-27 20:37:28 +08:00
何冠峰
7d9e00a574 update resource package 2025-02-27 18:15:02 +08:00
何冠峰
7382afe535 Update CHANGELOG.md 2025-02-27 17:43:10 +08:00
何冠峰
af7d4774d6 Update package.json 2025-02-27 17:43:02 +08:00
何冠峰
520a8a0623 code style 2025-02-27 17:14:20 +08:00
何冠峰
fbd0d8ec40 code style 2025-02-27 17:14:12 +08:00
何冠峰
3fea98ce4c fix #480 2025-02-27 17:13:49 +08:00
何冠峰
7c561ce254 update resource package 2025-02-27 17:01:26 +08:00
何冠峰
522ddb5115 update resource package
增加CustomPlayMode运行模式
2025-02-27 16:31:56 +08:00
何冠峰
47f5790507 update resource package
CreateBundleDownloader下载器增加参数:recursiveDownload
2025-02-27 10:31:05 +08:00
何冠峰
0cdcfe7f52 update file system 2025-02-26 19:31:06 +08:00
何冠峰
e4d69d869b update resource package
修复2.3.1版本 抖音和微信小游戏 下载器不生效的问题。
2025-02-26 14:22:59 +08:00
何冠峰
61afb70cb9 Update CHANGELOG.md 2025-02-25 14:17:41 +08:00
何冠峰
79580697a1 Update package.json 2025-02-25 14:17:32 +08:00
何冠峰
6cb74760b0 update extension sample 2025-02-25 14:06:36 +08:00
何冠峰
c758aa81ff update runtime code
重构了OperationSystem的机制。从列表模式修改为链模式
2025-02-25 12:18:16 +08:00
何冠峰
400c2ccefe code style 2025-02-22 16:29:25 +08:00
何冠峰
64e9734bbe update sapce shooter 2025-02-22 14:14:18 +08:00
何冠峰
f6244885be update diagnostic system
优化了Debugger窗口的显示页面
2025-02-22 14:14:05 +08:00
何冠峰
82c57c382f update TableView
支持Counter
2025-02-21 16:54:43 +08:00
何冠峰
7eacb46555 update resource package 2025-02-21 15:29:42 +08:00
何冠峰
d9c911d89b update asset bundle reporter 2025-02-20 18:50:26 +08:00
何冠峰
a3ceb3dcb6 update asset bundle builder 2025-02-20 12:04:42 +08:00
何冠峰
a5b68b28b2 update asset bundle builder 2025-02-20 11:27:44 +08:00
何冠峰
bd285faf37 update space shooter 2025-02-20 11:27:30 +08:00
何冠峰
8a4960b560 code style 2025-02-20 11:02:59 +08:00
何冠峰
83c6ae2057 update asset bundle builder
修复怀旧依赖模式下,TAG传染不正确的问题。
2025-02-20 11:01:25 +08:00
何冠峰
b71563e889 Update EBuildBundleType.cs 2025-02-20 10:02:12 +08:00
何冠峰
79e0cf85f9 Update CHANGELOG.md 2025-02-19 19:10:36 +08:00
何冠峰
e996eaa008 Update package.json 2025-02-19 19:10:28 +08:00
何冠峰
5088c9e985 update asset bundle builder 2025-02-19 18:46:39 +08:00
何冠峰
610b3c6d32 Update FileSystemParameters.cs 2025-02-19 18:36:43 +08:00
何冠峰
cc7290f10e update operation system
快速启动模式
2025-02-19 18:36:33 +08:00
何冠峰
576b842368 support legacy dependency mode
YOOASSET_LEGACY_DEPENDENCY
2025-02-19 18:27:23 +08:00
何冠峰
d23c0ba715 update space shooter 2025-02-18 19:35:46 +08:00
何冠峰
98e19baebd Update TextureSchema.cs 2025-02-18 19:34:41 +08:00
何冠峰
f5947db44a Update ReorderableListView.cs 2025-02-18 19:34:34 +08:00
何冠峰
e978164329 Update ReorderableListView.cs 2025-02-18 19:28:55 +08:00
何冠峰
966c8f2efa update space shooter 2025-02-18 18:41:05 +08:00
何冠峰
a57fec3d71 update UIElements 2025-02-18 18:38:00 +08:00
何冠峰
84844eda20 update UIElements 2025-02-18 17:31:49 +08:00
何冠峰
698cdcba61 update AssetArtScanner 2025-02-17 18:18:07 +08:00
何冠峰
1d6c9393d4 Update AssetBundleCollector
支持列表元素上下拖拽排序
2025-02-17 17:54:46 +08:00
何冠峰
b654ac156d update AssetArtScanner
支持列表元素上下拖拽排序
2025-02-17 17:54:34 +08:00
何冠峰
d133a9a692 update extension sample 2025-02-17 15:44:41 +08:00
何冠峰
d55db19f0e update extension sample
微信小游戏和抖音小游戏AssetBundle使用插件卸载机制。
2025-02-14 16:37:23 +08:00
何冠峰
e3fc3df32c update space shooter 2025-02-14 12:05:30 +08:00
何冠峰
f2334da72d update extension sample 2025-02-14 12:05:24 +08:00
何冠峰
2902b6c2cf fix #472 2025-02-14 11:29:13 +08:00
何冠峰
dfa95b57b9 Update CHANGELOG.md 2025-02-14 10:03:39 +08:00
何冠峰
33a2cf66d0 Update CHANGELOG.md 2025-02-14 10:03:15 +08:00
何冠峰
5f52cf5b51 Update package.json 2025-02-14 10:03:09 +08:00
何冠峰
9d07905f2d fix #471 2025-02-13 20:14:33 +08:00
何冠峰
26dbe9dfdd update extension sample 2025-02-13 19:08:23 +08:00
何冠峰
98c5851071 update extension file system
解决微信小游戏预下载和正常下载冲突的问题
2025-02-13 18:57:39 +08:00
何冠峰
a6ee571d65 update file system 2025-02-13 18:56:24 +08:00
何冠峰
a138701afe update extension sample
抖音小游戏支持资源加密
2025-02-13 12:12:52 +08:00
何冠峰
e52bdea255 fix #467
微信小游戏资源加密
2025-02-13 12:02:09 +08:00
何冠峰
068a712a30 Merge pull request #470 from suxf/dev
fix: 微信加密资源解密错误
2025-02-13 10:13:28 +08:00
枫似锦
80a5300648 fix: 微信加密资源解密错误 2025-02-13 00:12:26 +08:00
何冠峰
0c36e458f7 update space shooter 2025-02-12 17:43:15 +08:00
何冠峰
b2fa52e4c4 update AssetArtScanner 2025-02-12 17:43:07 +08:00
何冠峰
151e978e5b update space shoot 2025-02-12 16:29:26 +08:00
何冠峰
9e806861ec update extension sample 2025-02-12 16:28:31 +08:00
何冠峰
a9a9368b9b update test sample 2025-02-12 16:27:51 +08:00
何冠峰
7936ba31ea update file system
WebGL网页平台支持资源加密。
2025-02-12 16:27:30 +08:00
何冠峰
afc456de9a Update UnloadAllAssetsOperation.cs 2025-02-12 14:44:02 +08:00
何冠峰
a98db0ba83 update extension sample 2025-02-12 14:43:51 +08:00
何冠峰
fb8720edd3 update extension sample
抖音小游戏支持文件加密。
2025-02-12 11:59:09 +08:00
何冠峰
2aa2a0ac3a update space shooter 2025-02-12 11:46:38 +08:00
何冠峰
0531b6ef3a update extension sample 2025-02-12 11:45:12 +08:00
何冠峰
24142de11f update extension sample
支持微信小游戏文件加密
2025-02-12 11:23:27 +08:00
何冠峰
7fad6eb70b update services
增加WebGL端解密接口
2025-02-12 11:22:09 +08:00
何冠峰
f60227abdf Merge pull request #469 from suxf/dev
优化微信小游戏文件系统逻辑
2025-02-12 10:10:32 +08:00
枫似锦
18d6a74c53 Merge branch 'dev' of https://github.com/suxf/YooAsset into dev 2025-02-12 00:30:22 +08:00
枫似锦
03d06ba657 优化微信小游戏文件系统逻辑 2025-02-12 00:29:10 +08:00
何冠峰
07086b68c8 update extension sample
优化了抖音小游戏文件系统缓存机制
2025-02-11 18:44:51 +08:00
何冠峰
0a85f3126f update extension sample
优化了微信小游戏文件系统缓存机制。
2025-02-11 18:18:29 +08:00
何冠峰
efa4180340 update resource manager
UnloadUnusedAssetsOperation逻辑里移除了Resources.UnloadUnusedAssets调用
2025-02-11 18:15:45 +08:00
何冠峰
fb06f2aa11 update resource manager
UnloadAllAssetsAsync新增UnloadAllAssetsOptions参数
2025-02-11 17:32:31 +08:00
何冠峰
ce023cedb8 update extension sample 2025-02-11 15:13:45 +08:00
何冠峰
3d1a28a50e update file system 2025-02-11 15:09:23 +08:00
何冠峰
5d2d0b4168 fix #341 2025-02-11 10:20:33 +08:00
何冠峰
fa985a5a93 Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2025-02-11 09:55:38 +08:00
何冠峰
40f9937b60 update space shooter 2025-02-11 09:55:37 +08:00
何冠峰
c543c629c3 Merge pull request #466 from suxf/dev
fix:微信小游戏缓存文件系统查询机制不生效
2025-02-11 09:43:16 +08:00
何冠峰
f861279c49 Update CHANGELOG.md 2025-02-10 20:04:35 +08:00
何冠峰
ee89f81d46 Update package.json 2025-02-10 20:04:31 +08:00
何冠峰
6d216561f8 fix #468 2025-02-10 20:00:48 +08:00
枫似锦
0a96e583d3 Merge branch 'dev' of https://github.com/suxf/YooAsset into dev 2025-02-10 16:39:31 +08:00
枫似锦
c9d263c60d fix:微信小游戏缓存文件系统查询机制不生效 2025-02-10 16:38:23 +08:00
何冠峰
2d6488abf4 update AssetArtScanner
配置和报告容错性检测
2025-02-10 16:21:43 +08:00
何冠峰
7dfbac4a24 update AssetBundleCollector 2025-02-10 16:19:07 +08:00
何冠峰
7cfe4cb2c9 fix #465 2025-02-10 16:17:38 +08:00
何冠峰
30cba8ca5f Update CHANGELOG.md 2025-02-08 14:43:41 +08:00
何冠峰
e9261a0ec0 Update package.json 2025-02-08 14:43:39 +08:00
何冠峰
89ee22837d Update BuildParameters.cs 2025-02-08 14:35:10 +08:00
何冠峰
939f3747cd Update AssetBundleCollectorSetting.cs 2025-02-08 14:07:20 +08:00
何冠峰
f72814a51b fix #462 2025-02-08 11:45:06 +08:00
何冠峰
94ee2ba5c1 update test sample 2025-02-08 10:10:39 +08:00
何冠峰
fd9533d63f update extension sample 2025-02-08 10:10:18 +08:00
何冠峰
6571faae4e update AssetBundleBuilder
ScriptableBuildParameters类新增BuiltinShadersBundleName和MonoScriptsBundleName字段
2025-02-08 10:09:52 +08:00
何冠峰
e031498d5b update UIElements 2025-02-07 18:47:05 +08:00
何冠峰
31a0017351 Merge pull request #455 from suxf/dev
fix: 拷贝内置资源路径不正确
2025-02-07 16:27:15 +08:00
何冠峰
6e8cb0366d update extension sample
抖音小游戏文件重命名
2025-02-07 16:21:25 +08:00
何冠峰
a02b3fbf6e update extension sample
优化了小游戏文件系统的缓存机制。
2025-02-07 15:30:53 +08:00
何冠峰
37a663e0e1 update file system 2025-02-07 15:26:49 +08:00
何冠峰
e925d9892f fix #448 2025-02-06 17:43:40 +08:00
何冠峰
e7907eeaa7 fix #454
内置文件系统新增COPY_BUILDIN_PACKAGE_MANIFEST参数
2025-02-06 17:35:10 +08:00
何冠峰
644e6655ff update extension sample 2025-02-06 16:44:25 +08:00
何冠峰
20c07af504 update YooAssetSettings 2025-02-06 16:43:55 +08:00
何冠峰
38471cdd6c fix #452 2025-02-06 11:49:21 +08:00
何冠峰
0b5d16bd0e fix #456 2025-02-06 11:15:09 +08:00
何冠峰
203b9994df update AssetArtReporter 2025-02-05 19:04:05 +08:00
何冠峰
e76bbb6a85 update space shooter 2025-02-05 18:49:20 +08:00
何冠峰
4e6c146bde update UIElements 2025-02-05 18:49:11 +08:00
何冠峰
7e1dc7ef24 update UIElements 2025-02-05 17:26:19 +08:00
何冠峰
698d81a433 update AssetBundleDebugger 2025-02-05 10:51:31 +08:00
何冠峰
012f9b9f03 update UIElements 2025-02-05 10:38:47 +08:00
何冠峰
12bd282ace update space shooter 2025-01-24 00:43:27 +08:00
何冠峰
31a89fa1a3 update asset art reporter 2025-01-24 00:43:16 +08:00
何冠峰
57d1e92e59 update space shooter 2025-01-23 15:01:48 +08:00
何冠峰
377fca20d9 Update AssetArtReporterWindow.cs 2025-01-22 20:00:47 +08:00
何冠峰
415f844982 update asset art scanner 2025-01-22 19:17:05 +08:00
何冠峰
cbb8472153 update space shooter 2025-01-22 18:29:08 +08:00
何冠峰
c85ced89ef update space shooter 2025-01-22 18:28:15 +08:00
何冠峰
d5b8c90c94 update asset art scanner 2025-01-22 18:28:01 +08:00
何冠峰
9bcfb04f91 update space shooter 2025-01-22 17:23:23 +08:00
何冠峰
ae0fbd4b10 update asset art scanner 2025-01-22 17:22:45 +08:00
何冠峰
ef4f011cf6 update asset art scanner 2025-01-22 16:33:33 +08:00
何冠峰
7cc985205a update AssetArtScanner
资源扫描工具
2025-01-22 15:19:16 +08:00
何冠峰
a38b76eb8f update UIElements 2025-01-22 15:16:44 +08:00
阿枫
9f844912cf fix: 拷贝内置资源路径不正确 2025-01-21 14:10:35 +08:00
何冠峰
d72b0b10d4 update asset bundle reporter 2025-01-20 19:14:45 +08:00
何冠峰
655f756d56 update asset bundle debugger 2025-01-20 19:14:29 +08:00
何冠峰
912e2c28a3 update UIElements 2025-01-20 19:12:23 +08:00
何冠峰
9add447566 update asset bundle reporter 2025-01-20 17:14:47 +08:00
何冠峰
7c435f6dc0 update UIElements 2025-01-20 17:13:20 +08:00
何冠峰
5e2fc84ebf update UIElements 2025-01-20 10:07:16 +08:00
何冠峰
793a57647d update table view
新增单元格视图类
2025-01-17 16:23:31 +08:00
何冠峰
c32e7bc525 Update YooAssets.cs 2025-01-17 15:21:35 +08:00
何冠峰
20fac33efc fix #424 2025-01-14 16:43:44 +08:00
何冠峰
8cf356cadb fix #447 2025-01-14 16:03:24 +08:00
何冠峰
17d2c8bf0a Update CHANGELOG.md 2025-01-14 14:32:21 +08:00
何冠峰
3dec5ac004 Update LICENSE.md 2025-01-14 14:32:11 +08:00
何冠峰
cf2ada8f2b Update package.json 2025-01-14 14:32:08 +08:00
何冠峰
c801f601d3 fix #438 2025-01-14 14:19:24 +08:00
何冠峰
6a97704dab update test sample 2025-01-07 15:14:43 +08:00
何冠峰
ee6c8301c4 update asset bundle builder 2025-01-07 10:06:03 +08:00
何冠峰
de35f4308d update extension sample
修复小游戏插件验证清单方法不对的问题
2025-01-04 15:59:12 +08:00
何冠峰
3d4ed38f17 update extension sample
修正扩展文件系统类编译错误
2025-01-04 14:10:10 +08:00
何冠峰
a84f981147 update test scene 2025-01-03 19:15:51 +08:00
何冠峰
b70d821384 update space shooter 2025-01-03 19:15:38 +08:00
何冠峰
bc7c6c1f33 update package invoke builder
新增包裹构建器,运行时构建资源包裹
2025-01-03 19:15:29 +08:00
何冠峰
2a8761c29e Update CHANGELOG.md 2025-01-03 18:10:59 +08:00
何冠峰
0c732755ec Update package.json 2025-01-03 18:10:53 +08:00
何冠峰
5c638d713e update space shooter 2025-01-03 17:49:20 +08:00
何冠峰
8ff16f7205 update test sample 2025-01-03 17:27:04 +08:00
何冠峰
6bf8e3643b fix #428 2025-01-03 15:44:44 +08:00
何冠峰
6ab704bb77 fix #435 2025-01-03 15:37:32 +08:00
何冠峰
41329f3bbc update space shooter 2025-01-03 15:09:29 +08:00
何冠峰
a59ebd69b4 update extension sample 2025-01-03 15:09:20 +08:00
何冠峰
278b6e3cc8 fix #429
ClearCacheBundleFilesAsync重命名为ClearCacheFilesAsync
2025-01-03 15:08:57 +08:00
何冠峰
1d0c0ee7cb update asset bundle collector 2025-01-03 10:23:27 +08:00
何冠峰
a8bf0a62fa update asset bundle collector
增加视频文件打包规则
2025-01-02 20:56:18 +08:00
何冠峰
fc58fb27e2 Update AssemblyInfo.cs 2025-01-02 20:55:57 +08:00
何冠峰
b1abeb4ec2 update test sample
单元测试用例
2025-01-02 20:55:47 +08:00
何冠峰
d9b7f33bde update space shooter 2025-01-02 20:15:20 +08:00
何冠峰
c0a1061204 update extension sample
更新抖音小游戏文件系统
2025-01-02 18:45:54 +08:00
何冠峰
7cbdfeec51 fix #434 2025-01-02 15:58:49 +08:00
何冠峰
381c16d574 update space shooter 2025-01-02 14:10:21 +08:00
何冠峰
3e6be2f293 update resource package 2025-01-02 14:10:11 +08:00
何冠峰
1bd62c4673 update space shooter 2025-01-02 10:51:32 +08:00
何冠峰
04aa4067cd update space shooter 2025-01-02 10:47:07 +08:00
何冠峰
499fb8239e fix #433 2025-01-02 10:46:52 +08:00
何冠峰
fe75491024 update resource manager
整理文件目录结构
2025-01-02 10:45:56 +08:00
何冠峰
8803003cf7 fix #432
FileSystemParameters.RootDirectory字段重命名为PackageRoot
2024-12-31 19:22:00 +08:00
何冠峰
5a850aef07 Update AssetBundleCollectorSettingData.cs 2024-12-31 16:43:50 +08:00
何冠峰
d1d6e023c4 update space shooter 2024-12-31 15:13:13 +08:00
何冠峰
4370ed544f update cache system 2024-12-31 11:15:46 +08:00
何冠峰
42c87519e1 Update SceneHandle.cs 2024-12-31 10:16:29 +08:00
何冠峰
769134eaf9 update cache system
移除ThreadSyncContext类
2024-12-31 10:16:20 +08:00
何冠峰
51b688bbdd fix #426 2024-12-31 10:02:01 +08:00
何冠峰
748e74e515 Update CHANGELOG.md 2024-12-30 17:13:07 +08:00
何冠峰
d1d3ad9869 Update package.json 2024-12-30 17:12:59 +08:00
何冠峰
f9b72a22ae fix #423 2024-12-30 16:27:50 +08:00
何冠峰
766cf90a19 fix #422 2024-12-30 10:27:04 +08:00
何冠峰
8a2dc86cf7 update code summary 2024-12-27 18:37:29 +08:00
何冠峰
5ca54b88fa update download system 2024-12-27 17:51:21 +08:00
何冠峰
7257c8778d Merge pull request #332 from Pro-Ly/dev
fix url path special cases
2024-12-27 17:45:00 +08:00
何冠峰
dc21696ae1 update extension sample
新增示例代码HandleBaseExtension
2024-12-27 17:34:22 +08:00
何冠峰
7f566e5388 update extension sample
重新整理目录结构
2024-12-27 17:29:00 +08:00
何冠峰
fe352ceb84 update operation system
新增字段PackageName
2024-12-27 17:23:55 +08:00
何冠峰
10750a0123 update space shooter 2024-12-27 17:08:59 +08:00
何冠峰
f2e6da649b update resource package
重构了下载器的委托方法
2024-12-27 17:08:39 +08:00
何冠峰
9737cd06dd Merge pull request #392 from absences/newv
upgrade deprecated event in newer version
2024-12-27 16:06:24 +08:00
何冠峰
df8cf4d9ca update extension sample 2024-12-27 16:04:01 +08:00
何冠峰
36b4cbb8c2 Update DefaultAddressRule.cs 2024-12-27 16:03:47 +08:00
何冠峰
bae84f65da Merge pull request #370 from BoysheO/patch-1
append an addressRule
2024-12-27 15:50:14 +08:00
何冠峰
313ec2d100 Merge pull request #418 from GodChouyu/dev
Fix a bug when initializing DefaultWebRemoteFileSystem.
2024-12-27 15:16:38 +08:00
何冠峰
bfda5ec952 Update CHANGELOG.md 2024-12-27 15:09:04 +08:00
何冠峰
248bdba839 Update package.json 2024-12-27 15:08:54 +08:00
何冠峰
75dd3d0e5e fix #410 2024-12-27 12:02:08 +08:00
何冠峰
8944ec0e02 fix #419
优化场景卸载逻辑
2024-12-27 11:53:55 +08:00
GodChouyu
25c5683a09 Fix a bug when initializing DefaultWebRemoteFileSystem. 2024-12-27 10:16:57 +08:00
何冠峰
069e29ac07 update resource manager 2024-12-27 10:07:15 +08:00
何冠峰
942e4bf672 fix #413 2024-12-26 21:53:02 +08:00
何冠峰
dca37a3794 update resource package 2024-12-26 21:35:44 +08:00
何冠峰
f84419b7a6 fix #417 2024-12-26 15:43:58 +08:00
何冠峰
aa3a049985 fix #414 2024-12-26 14:57:37 +08:00
何冠峰
3f8c7bd91f update space shooter 2024-12-26 12:17:37 +08:00
何冠峰
11984d6972 update asset bundle reporter 2024-12-26 12:17:18 +08:00
何冠峰
31b0a3fb54 update extension sample
移除冗余的命名空间
2024-12-26 10:55:58 +08:00
何冠峰
666d0b53a6 fix script compile error in unity 2020 2024-12-26 10:55:30 +08:00
何冠峰
df77df4854 update space shooter
修正编译错误
2024-12-25 18:49:12 +08:00
何冠峰
4f75248f5b Update CHANGELOG.md 2024-12-25 18:47:41 +08:00
何冠峰
2b56f4469d Update package.json 2024-12-25 18:47:27 +08:00
何冠峰
8d1f0d2010 update extension sample 2024-12-25 17:24:48 +08:00
何冠峰
16117b67f1 update sapce shooter 2024-12-24 18:49:14 +08:00
何冠峰
4fc0d06908 update resource manager
重构运行时核心代码
2024-12-24 18:45:37 +08:00
何冠峰
6254d00bb5 update file system
重构运行时核心代码
2024-12-24 18:23:19 +08:00
何冠峰
6d6fd3af2c update assetbundle builder 2024-12-24 17:35:26 +08:00
何冠峰
16344393a1 update resource package
增加新方法:public PackageDetails GetPackageDetails()
2024-12-19 17:25:31 +08:00
何冠峰
36f561a595 update extension sample 2024-12-19 14:42:33 +08:00
何冠峰
f5f024b1d6 update extension sample 2024-12-19 14:09:35 +08:00
何冠峰
429f68ff64 update asset bundle builder 2024-12-19 12:24:19 +08:00
何冠峰
f9074518dd update space shooter 2024-12-19 11:28:49 +08:00
何冠峰
bda803761b update extension sample 2024-12-19 11:28:27 +08:00
何冠峰
d3c1c5acb0 fix #407 2024-12-19 11:15:58 +08:00
何冠峰
dcaafedabb update YooAssetSettings
移除配置参数:ManifestFileName
2024-12-17 18:08:40 +08:00
何冠峰
985c76d8ce fix #291
cache file system 新增参数:最大并发数和每帧请求最大数
2024-12-17 17:14:59 +08:00
何冠峰
8c532798cb update file system 2024-12-17 15:37:47 +08:00
何冠峰
17aed56270 update extension smaple 2024-12-17 15:28:49 +08:00
何冠峰
1f07411dde fix #293
Default Yoo Folder Name 可配空
2024-12-17 15:27:36 +08:00
何冠峰
906e0e3554 Update TaskCreateManifest.cs 2024-12-17 15:24:13 +08:00
何冠峰
22958923ad Update EditorSimulateBuildpipelineViewer.cs 2024-12-17 09:54:14 +08:00
何冠峰
a5f94198c0 update sapce shooter 2024-12-16 19:38:29 +08:00
何冠峰
8a2bac8770 refactor : editor simulate build
移除了枚举定义类型:EDefaultBuildPipeline
修改了EditorSimulateModeHelper.SimulateBuild()方法
2024-12-16 19:37:09 +08:00
何冠峰
3fd24f6f19 fix #391 2024-12-16 18:38:46 +08:00
何冠峰
c30292013b Update UnloadUnusedAssetsOperation.cs 2024-12-16 18:13:10 +08:00
何冠峰
edd6db731f update extension sample 2024-12-16 18:12:45 +08:00
何冠峰
19e0c7b01a fix #307 2024-12-16 18:05:27 +08:00
何冠峰
58fc76b8d2 fix #403
移除了EBuildMode枚举类型
2024-12-16 17:45:07 +08:00
何冠峰
1638bb301d fix #406 2024-12-16 16:45:05 +08:00
何冠峰
f0ed677d86 refactor : remove DryRunBuild build mode
移除演练构建模式
2024-12-13 14:32:17 +08:00
何冠峰
4b0c52d2dd fix #404 2024-12-13 14:10:12 +08:00
何冠峰
5f4e1d0b2f update package
scriptablebuildpipeline版本切换为1.21.25
2024-12-13 11:44:55 +08:00
何冠峰
a98a48a58d Update TaskCreateManifest.cs 2024-12-13 11:12:09 +08:00
何冠峰
763054884b fix #387 2024-12-13 11:00:30 +08:00
何冠峰
376088e63c update space shoot 2024-12-13 10:25:56 +08:00
何冠峰
c614ba4705 fix #402 2024-12-13 10:25:16 +08:00
何冠峰
14ea408fec fix #386 2024-12-12 18:13:33 +08:00
何冠峰
038a52f7fc Update ResourcePackage.cs 2024-12-12 17:59:04 +08:00
何冠峰
341bd5947f update extension sample 2024-12-12 17:55:39 +08:00
何冠峰
b5d857d2f1 fix #380
新增示例文件 CopyBuildinManifestOperation
2024-12-12 17:53:34 +08:00
何冠峰
97f9a3d4b1 refactor : default cache file system 2024-12-12 17:35:42 +08:00
何冠峰
9607d7135b refactor : cache system 2024-12-12 15:16:34 +08:00
何冠峰
b1338a9ffd refactor : cache file system 2024-12-12 15:00:08 +08:00
何冠峰
bf1e3da298 feat : remove delivery file system
Host Play Mode 移除了DeliveryFileSystemParameters
2024-12-11 18:43:15 +08:00
何冠峰
a91cbee50c update space shooter 2024-12-11 18:24:55 +08:00
何冠峰
15fbbf3873 Update InitializeParameters.cs 2024-12-11 18:24:40 +08:00
何冠峰
f73abba79f feat : web play mode support remote services
WebPlayMode支持跨域加载。
2024-12-11 18:19:09 +08:00
何冠峰
5fa9ebee80 feat : package manifest add note info
清单文件增加备注信息
2024-12-11 11:22:50 +08:00
何冠峰
d890ccd5e6 feat : default editor file system support async simulate frame
编辑器文件系统支持异步模拟加载帧数
2024-12-11 10:43:13 +08:00
何冠峰
e76a782a80 Update ResourcePackage.cs 2024-12-11 10:04:33 +08:00
何冠峰
0f7c5b2564 Update ResourcePackage.cs 2024-12-10 18:41:09 +08:00
何冠峰
fcf0f34d5a update resource manager 2024-12-10 18:00:13 +08:00
何冠峰
acf2301028 refactor : wait for sync complete 2024-12-10 16:48:08 +08:00
何冠峰
9bc0577423 Update DefaultIgnoreRule.cs
忽略Gizmos和编辑器资源
2024-12-10 15:18:34 +08:00
何冠峰
d037ce5b86 Update LoadBundleFileOperation.cs 2024-12-10 15:17:49 +08:00
unknown
02250c3352 upgrade deprecated method in newer version 2024-11-12 14:40:49 +08:00
何冠峰
cdaa45e163 Update README.md 2024-11-07 10:08:10 +08:00
何冠峰
2b9014f4d8 update space shooter
修正PatchOperation不支持原生文件
2024-10-29 17:07:53 +08:00
何冠峰
75a013d961 Update InstantiateOperation.cs
禁用引擎提供的GameObject对象的异步实例化
2024-10-28 12:11:41 +08:00
何冠峰
27563fa58e Merge pull request #379 from rickytheoldtree/patch-1
Update README.md
2024-10-22 17:34:08 +08:00
何冠峰
55f958266c Update InstantiateOperation.cs
use Object.InstantiateAsync
2024-10-17 10:52:25 +08:00
何冠峰
d980b55997 update operation system 2024-10-17 10:51:17 +08:00
rickytheoldtree
7232caa5c0 Update README.md 2024-10-14 11:55:23 +08:00
何冠峰
c0df366676 update wechat file system 2024-09-30 18:00:02 +08:00
何冠峰
8e7a43275f update extension sample 2024-09-30 17:59:25 +08:00
何冠峰
d3567d8dd5 Merge pull request #368 from JackCheng-314/EditorGitYooAsset
Wechat Clear Cache
2024-09-30 14:52:16 +08:00
jcakCheng
e9539636ac 误删除,调用微信小游戏接口删除缓存文件目录下所有文件 2024-09-13 21:05:15 +08:00
jcakCheng
093dd25e0f 微信小游戏相关代码,迁移至WechatFileSystem,修改packageversion缓存逻辑 2024-09-13 20:59:46 +08:00
jcakCheng
e0427d3062 微信小游戏,PackageVersion请求url添加_appendTimeTicks;修改unusedCache路径判断 2024-09-13 11:44:40 +08:00
BoysheO
9e2030c83d Update DefaultAddressRule.cs
添加一个寻址规则,效果极好
2024-09-10 11:36:46 +08:00
jcakCheng
0627641845 添加微信小游戏删除缓存根目录之后重启小游戏逻辑,WX.CleanAllFileCache 2024-09-09 20:33:28 +08:00
jcakCheng
4bbcc3c73d 修改宏的条件 2024-09-09 20:03:07 +08:00
jcakCheng
945842c0e7 提交微信缓存相关逻辑,删除全部缓存和部分无用缓存 2024-09-09 19:52:42 +08:00
何冠峰
02ba98f120 style editor code 2024-09-05 10:14:00 +08:00
何冠峰
688f8ec26c feat : webgl platform logs 2024-09-02 11:29:01 +08:00
何冠峰
7652de0129 fix #359 2024-09-02 10:30:21 +08:00
何冠峰
3f027e5456 fix #361 2024-08-30 18:45:58 +08:00
何冠峰
6a17335231 Update ByteGameFileSystem.cs 2024-08-27 15:46:04 +08:00
何冠峰
ebf0dd9e46 Update InstantiateOperation.cs 2024-08-27 15:45:55 +08:00
何冠峰
04bd352a05 Update BuildBundleInfo.cs
适配unity2019
2024-08-27 15:45:46 +08:00
何冠峰
fa4ebfe3be fix #349 2024-08-22 22:05:08 +08:00
何冠峰
87421bb391 style : add log 2024-08-22 15:19:36 +08:00
何冠峰
c35e22fbd7 feat : Gaem async operation add Abort method. 2024-08-22 15:18:57 +08:00
何冠峰
94623d8dc0 feat : Instantiate add actived param.
实例化对象方法增加激活参数。
2024-08-22 15:18:31 +08:00
何冠峰
50eed2be10 update extension sample 2024-08-21 17:36:43 +08:00
何冠峰
e9b7336146 perf : optimize asset bundle builder 2024-08-21 17:36:27 +08:00
何冠峰
fbec06fa81 update extension sample 2024-08-19 12:29:54 +08:00
何冠峰
9fe8dad72d update extension sample
增加抖音小游戏文件系统
2024-08-19 12:24:54 +08:00
何冠峰
3046bbe697 Merge pull request #342 from miuleung/dev
Fix File Dialog Cancel Error Log
2024-08-15 14:34:37 +08:00
何冠峰
7089952895 Update CHANGELOG.md 2024-08-15 11:55:53 +08:00
何冠峰
737d2a796b Update CHANGELOG.md 2024-08-15 11:54:39 +08:00
何冠峰
e25fd14675 Update package.json 2024-08-15 11:54:34 +08:00
何冠峰
c55dc713f4 fix : fixed the host play mode init stuck
修复HostPlayMode初始化卡死问题。
2024-08-15 11:53:25 +08:00
miuleung
40ef17edcd Merge branch 'tuyoogame:dev' into dev 2024-08-14 15:15:50 +08:00
何冠峰
418536ded1 perf : check collect asset type
检测收集的资源类型是否有效
2024-08-13 19:13:26 +08:00
miuleung
c156b5c0a7 Fix File Dialog Cancel Error Log
选择文件时取消报错修复
2024-08-13 16:05:20 +08:00
何冠峰
ae454b72dc update extension sample 2024-08-13 10:54:29 +08:00
何冠峰
d34d1117a0 Update CHANGELOG.md 2024-08-13 10:30:52 +08:00
何冠峰
a5f3767cbc Update package.json 2024-08-13 10:30:37 +08:00
何冠峰
3bdb339f54 style : resource package 2024-08-13 10:19:29 +08:00
何冠峰
22cb3c3942 style : resource manager 2024-08-13 10:10:43 +08:00
何冠峰
e5f5241879 fix #311 2024-08-12 20:18:03 +08:00
何冠峰
79ac231df2 feat : builtin file system can be empty in host play mode.
HostPlayMode模式下内置文件系统可以为空。
2024-08-12 19:10:57 +08:00
hevinci
b7b375092f refactor : process build logic 2024-08-03 19:01:55 +08:00
hevinci
f86ea04521 refactor : operation system 2024-08-03 19:01:18 +08:00
hevinci
738c02f58f update space shooter 2024-08-03 18:43:28 +08:00
hevinci
d017688416 feat : the bundle file decryption
资源文件解密
2024-08-03 18:43:12 +08:00
何冠峰
6b56275f87 Merge pull request #326 from absences/decrypt
Assetbundle加载增加解密方法
2024-08-03 17:03:45 +08:00
hevinci
b89f00130e refactor load scene code 2024-08-03 16:53:25 +08:00
何冠峰
4f58c54eff Merge pull request #333 from dadahsueh/dev
feat : add load scene parameter LocalPhysicsMode
2024-08-03 16:09:49 +08:00
Dada Hsueh
9001be21ac feat : add load scene parameter LocalPhysicsMode 2024-08-01 11:04:43 +08:00
Pro-Ly
be3fa0b688 fix url path special cases 2024-07-31 23:28:47 +08:00
hevinci
b421e7d2f8 Update CHANGELOG.md 2024-07-31 12:06:23 +08:00
hevinci
0e7c14abde Update package.json 2024-07-31 12:06:15 +08:00
hevinci
caf072ed9b Update DefaultBuildinFileSystemBuild.cs 2024-07-31 12:02:07 +08:00
hevinci
51f2709956 Update EditorTools.cs 2024-07-31 12:01:29 +08:00
absences
0d5558f29f Update IDecryptionServices.cs 2024-07-29 14:34:21 +08:00
unknown
c6377ce544 原生文件加密/解密 2024-07-27 18:37:17 +08:00
unknown
07d34891ef Assetbundle加载增加解密方法 2024-07-27 17:23:26 +08:00
unknown
ddce031ee5 Assetbundle加载增加解密方法 2024-07-27 15:25:21 +08:00
hevinci
6680a6450b fix #325
适配unity2019引擎
2024-07-24 10:12:42 +08:00
hevinci
dc119b26c7 fix #321 2024-07-19 12:02:43 +08:00
hevinci
2cbfca4f3b update extension sample
着色器变种文件增加内部排序
2024-07-15 18:51:32 +08:00
何冠峰
7d8fce6f46 Update CHANGELOG.md 2024-07-10 16:54:45 +08:00
何冠峰
13ad50aef5 Update package.json 2024-07-10 16:54:43 +08:00
何冠峰
30245b3668 update extension sample 2024-07-10 16:50:19 +08:00
何冠峰
589eea7cf3 update file system
统一所有PlayMode的初始化行为
2024-07-09 23:37:20 +08:00
何冠峰
24c5108ce1 update asset bundle collector
适配团结引擎
2024-07-09 16:33:41 +08:00
何冠峰
21fbb01ce4 merge #317
根据NETAnalyzers调整代码
2024-07-08 18:54:07 +08:00
何冠峰
e664f20d34 update extension sample 2024-07-08 17:36:39 +08:00
何冠峰
b0ce14dc0e update file system
IFileSystem新增ReadFileData方法
2024-07-08 17:36:25 +08:00
何冠峰
d2b38cbc1b Update CHANGELOG.md 2024-07-07 18:04:21 +08:00
何冠峰
a6d978090c Update package.json 2024-07-07 18:04:19 +08:00
何冠峰
f9d40987eb update extension sample 2024-07-07 16:16:00 +08:00
何冠峰
cab710493e update file system 2024-07-07 16:15:42 +08:00
何冠峰
9970cf704b update space shooter 2024-07-07 16:02:22 +08:00
何冠峰
260867b588 update operation logic 2024-07-07 16:01:55 +08:00
何冠峰
25231ecd32 update resource manager 2024-07-07 09:45:01 +08:00
何冠峰
b282515c39 update extension sample 2024-07-07 00:52:50 +08:00
何冠峰
bafd15571a update file system 2024-07-07 00:52:17 +08:00
何冠峰
481711fd75 update space shooter 2024-07-05 20:21:51 +08:00
何冠峰
d09b52301a update extension sample 2024-07-05 20:20:38 +08:00
何冠峰
0c77ef628f update file system 2024-07-05 20:20:27 +08:00
何冠峰
54f585c67a update extension sample 2024-07-05 19:29:50 +08:00
何冠峰
a9e5e7fdd3 update file system 2024-07-05 19:29:34 +08:00
何冠峰
b151f968d7 update space shooter 2024-07-05 15:10:52 +08:00
何冠峰
86ef93caa3 update extension sample 2024-07-05 15:10:34 +08:00
何冠峰
75511397d6 update file system 2024-07-05 15:10:07 +08:00
何冠峰
db8d09d0d6 update extension sample
增加微信小游戏文件系统范例
2024-07-04 22:56:45 +08:00
何冠峰
02d70a476d update file system 2024-07-04 22:55:58 +08:00
何冠峰
9420f8561f update web file system 2024-07-04 21:59:24 +08:00
何冠峰
d43eb821b9 update sapce shooter 2024-07-04 20:49:18 +08:00
何冠峰
b82ede8bde update samples 2024-07-04 20:49:07 +08:00
何冠峰
ff02da5c54 refactor the runtime code
重构了运行时代码,支持全新的文件系统。
2024-07-04 20:36:26 +08:00
hevinci
2987d356b6 fix #308 2024-05-27 10:42:24 +08:00
hevinci
dc5f0b151b Update CHANGELOG.md 2024-05-16 17:20:58 +08:00
hevinci
dd5bcc3d9d Update package.json 2024-05-16 17:20:45 +08:00
hevinci
80188ae6e6 fix #295 2024-05-10 10:57:06 +08:00
hevinci
05e77dc166 update dependencies
SBP依赖库升级至2.1.3版本
2024-05-09 14:05:53 +08:00
hevinci
b9b8f8e170 style code 2024-04-26 16:06:49 +08:00
hevinci
c9cc09cbed fix #289 2024-04-26 16:05:37 +08:00
hevinci
bef90bf3b8 perf : check build pipeline parameter type 2024-04-26 16:05:13 +08:00
hevinci
a369efa429 fix #276 2024-04-12 11:25:12 +08:00
hevinci
370329b07d refactor : wechat game support
提供对微信小游戏缓存的查询接口
2024-04-11 19:51:34 +08:00
hevinci
e743a15fbc update extension sample 2024-04-09 20:09:12 +08:00
hevinci
10c8b52092 add packages files 2024-04-09 19:15:35 +08:00
hevinci
1461b91a94 fix #268
修复了挂起场景未解除状态前无法卸载的问题。
2024-04-03 17:14:16 +08:00
hevinci
b5ffd5005a fix #269
优化场景挂起流程,支持中途取消挂起操作。
2024-04-03 17:11:11 +08:00
hevinci
f06bd83dc3 style : add summry 2024-04-02 17:26:57 +08:00
hevinci
a1450ee78a refactor : build System Stability
工具类新增了FileSHA1Safely,FileMD5Safely,FileCRC32Safely等方法。
2024-04-02 13:04:11 +08:00
hevinci
4c619778c3 feat : support open harmony
支持华为鸿蒙系统
2024-03-13 15:50:46 +08:00
hevinci
4e8840cd93 update space shooter 2024-03-12 11:12:39 +08:00
hevinci
0a709f741a feat : asset bundle collector config upgrade compatible 2024-03-12 11:12:13 +08:00
hevinci
ef8229981e feat : add IIgnoreRule interface
支持自定义过滤规则
移除了IgnoreDefaultType收集参数
2024-03-12 10:33:54 +08:00
hevinci
2a5a2626a4 feat : add load scene sync method 2024-03-08 15:39:25 +08:00
hevinci
f4ddaedbf4 feat : add load scene sync method 2024-03-08 14:23:07 +08:00
hevinci
42104eb944 perf : check collector error 2024-03-08 11:39:48 +08:00
hevinci
fadc8e6fd6 feat : add shader pack rule and filter rule 2024-03-08 11:38:29 +08:00
hevinci
81747462b1 feat : add load scene sync method 2024-03-08 11:06:48 +08:00
何冠峰
c01adad2a0 Merge pull request #245 from absences/dev
fix path error
2024-03-04 11:13:47 +08:00
何冠峰
e598d60439 Merge pull request #249 from ZensYue/dev
移除场景成功之后再尝试卸载ab包
2024-03-04 11:12:45 +08:00
e
929cd23f35 移除场景成功之后再尝试卸载ab包 2024-03-03 23:41:28 +08:00
unknown
d1aca5b675 fix path error 2024-02-28 10:06:45 +08:00
hevinci
b67868868d style : correct typos 2024-02-26 17:42:04 +08:00
hevinci
af3bf8448c style : change file to unicode 2024-02-26 14:29:36 +08:00
hevinci
4170c60f0c style : The hash utility class is exposed 2024-02-21 10:10:37 +08:00
hevinci
0a7a883aae fix #244 2024-02-20 11:31:27 +08:00
hevinci
88a1184877 perf : optimize package manifest deserialize 2024-02-20 10:04:10 +08:00
hevinci
c7329fcab5 feat : remove space character for bundle name
移除资源包名里的空格字符
2024-02-20 09:55:49 +08:00
hevinci
6eb9a90a03 feat : add GetAllCacheFileInfosAsync method 2024-02-18 12:11:29 +08:00
hevinci
7586882a97 fix #236 2024-02-01 18:41:16 +08:00
hevinci
6f13c021b9 Update CHANGELOG.md 2024-01-17 12:11:25 +08:00
hevinci
5f30c92d44 Update package.json 2024-01-17 12:11:17 +08:00
hevinci
3e6c55d981 style : code comment 2024-01-10 15:04:29 +08:00
hevinci
de36f984d7 style : change macro name 2024-01-03 16:44:48 +08:00
hevinci
95328fe1a6 feat : wechat game cache query 2024-01-03 16:24:02 +08:00
hevinci
1fb78185ff feat : support share pack rule
支持共享资源打包规则
2024-01-03 15:13:28 +08:00
hevinci
58f9aea979 fix #223 2024-01-02 11:46:29 +08:00
hevinci
4d4bb1e34f fix #223 2024-01-02 11:06:50 +08:00
hevinci
6e1978ec10 fix #224 2024-01-02 10:35:41 +08:00
hevinci
d8a8afba5e Update CHANGELOG.md 2023-12-27 19:54:07 +08:00
hevinci
6e6f425bdd Update package.json 2023-12-27 19:54:05 +08:00
hevinci
9ebe92f832 refactor : asset bundle reporter 2023-12-27 18:24:31 +08:00
hevinci
cbdb84a69f fix #212 2023-12-27 18:20:37 +08:00
hevinci
67b2b886a8 fix #220 2023-12-26 11:40:47 +08:00
hevinci
2838289650 feat : the build report file add independ asset info 2023-12-26 11:30:19 +08:00
hevinci
4b68362fb8 update samples 2023-12-25 14:20:02 +08:00
hevinci
e8e7696a4d refactor : editor code 2023-12-25 14:19:55 +08:00
hevinci
82b2a5cc20 fix #210 2023-12-22 10:24:41 +08:00
hevinci
2332765932 style : Code text indent format 2023-12-21 19:49:50 +08:00
hevinci
552d689317 style : Code text indent format 2023-12-21 19:44:14 +08:00
hevinci
5e2d82d071 style : Code text indent format 2023-12-21 19:40:13 +08:00
hevinci
727f356eea style : Code text indent format 2023-12-21 19:29:26 +08:00
hevinci
544832c46a style : Code text indent format 2023-12-21 19:10:46 +08:00
hevinci
5c1d316d67 feat #203 2023-12-21 17:45:51 +08:00
hevinci
267ec77c37 fix #198
禁用的分组不再检测合法性
2023-12-21 17:33:08 +08:00
hevinci
c2a7106221 fix #202 2023-12-21 16:18:36 +08:00
hevinci
0e29e9823d update query services interface
内置文件和分发文件查询方法参数里增加了文件哈希值
2023-12-21 16:10:54 +08:00
hevinci
47962424eb fix #201
修复断点续传失效的问题
2023-12-21 12:06:06 +08:00
hevinci
505d23ca07 update space shooter sample 2023-12-13 09:56:36 +08:00
hevinci
d4fcb868d8 update resource package
修复下载器合并后重新计算下载字节数不正确的问题。
2023-11-22 11:13:39 +08:00
hevinci
6dd1f43445 fix #205 2023-11-18 17:12:41 +08:00
hevinci
2626cb6750 fix #195 2023-11-01 16:30:58 +08:00
hevinci
81a98ded8a update sapce shooter 2023-11-01 11:03:40 +08:00
hevinci
930f02765d Update package.json
升级SBP依赖版本,解决图集内精灵图片冗余问题
2023-11-01 11:03:16 +08:00
hevinci
a4ffa580b7 update asset bundle builder
remove RemoveSpriteAtlasRedundancy task.
2023-11-01 11:02:46 +08:00
hevinci
506612527d Update CHANGELOG.md 2023-10-27 17:24:35 +08:00
hevinci
74f9f2b0e6 Update package.json 2023-10-27 17:24:17 +08:00
hevinci
4119f02c60 update resource manager 2023-10-27 16:24:33 +08:00
hevinci
bc9a4e07e2 update operation system
异步操作增加执行优先级
2023-10-27 16:08:38 +08:00
hevinci
9418544264 update resource manager
初始化参数增加AutoDestroyAssetProvider
2023-10-26 19:07:51 +08:00
hevinci
460ea091bd fix #185 2023-10-26 17:11:56 +08:00
hevinci
64681db027 update resource manager 2023-10-25 18:45:30 +08:00
hevinci
992957e1e9 Merge branch 'dev' of https://github.com/tuyoogame/YooAsset into dev 2023-10-25 18:28:57 +08:00
hevinci
ce62dbc27f update resource manager
所有异步加载方法增加权重参数。
2023-10-25 18:28:55 +08:00
何冠峰
e2df967aa9 Merge pull request #190 from zy020118/patch-1
Update DownloadManager.cs
2023-10-25 14:13:29 +08:00
hevinci
5b4a188c0b update space shooter 2023-10-24 18:41:58 +08:00
hevinci
e8b5a58a90 update resource manager 2023-10-24 18:38:31 +08:00
swift
c3d5c13a80 Update DownloadManager.cs
WebGL平台改名遗漏 DefaultBuildPipeline->EDefaultBuildPipeline
2023-10-24 14:26:00 +08:00
hevinci
d30a8aefa4 update resource manager
优化ForceUnloadAllAssets方法逻辑
2023-10-19 19:39:14 +08:00
hevinci
194afe435a update resource manager
增加卸载指定资源的方法。
2023-10-19 16:28:30 +08:00
hevinci
82ef993d83 fix #180 2023-10-18 12:14:24 +08:00
hevinci
6d7177a3b5 Update CHANGELOG.md 2023-10-17 19:28:28 +08:00
hevinci
205dd58afd Update package.json 2023-10-17 19:27:39 +08:00
hevinci
d5d5063453 update editor windows 2023-10-17 19:03:11 +08:00
hevinci
f63fcf1227 update editor window localization 2023-10-17 12:03:11 +08:00
hevinci
0c70f27560 update editor
1. 编辑器界面支持本地化配置。
2. 资源构建过程中的异常输出增加错误码提示。
3. 修复了资源构建界面乱码问题。
4. 修复了自动收集着色器对依赖资源无效的问题。
2023-10-13 12:06:20 +08:00
hevinci
db889366ac update samples 2023-10-11 14:36:18 +08:00
hevinci
9476bbe562 update resource package 2023-10-11 14:36:02 +08:00
hevinci
1313e05d5d Update CHANGELOG.md 2023-10-11 10:23:21 +08:00
hevinci
8817b35517 Update package.json 2023-10-11 10:23:12 +08:00
hevinci
cfe8a77dd5 fix #179 2023-10-10 16:19:53 +08:00
hevinci
a874d17798 update samples 2023-10-10 12:17:54 +08:00
hevinci
5d9ef12577 update operation system 2023-10-10 12:17:01 +08:00
hevinci
b3a135e1a2 fix #178 2023-10-10 11:59:56 +08:00
hevinci
a25d03f073 update resource package 2023-10-08 17:42:10 +08:00
hevinci
589c0d3ce5 update resource package
下载器增加合并方法
2023-10-08 17:41:07 +08:00
hevinci
8457705807 fix #177 2023-10-08 15:31:39 +08:00
hevinci
ce7aefb744 fix #175 2023-10-07 18:51:52 +08:00
hevinci
499d7766db update extension 2023-10-07 18:51:27 +08:00
hevinci
988327c9bd Update CHANGELOG.md 2023-10-07 16:50:27 +08:00
hevinci
d0d0bf2b63 Update package.json 2023-10-07 16:50:24 +08:00
hevinci
feb34761ce update shader variant collector 2023-10-07 16:09:31 +08:00
hevinci
0ceeeb8c5b update download system
support to cancel download operation
2023-10-07 16:02:11 +08:00
hevinci
0c7289bbc8 remove shader variant collector 2023-10-07 15:04:14 +08:00
hevinci
e02fe2331d update asset bundle collector 2023-10-07 15:03:56 +08:00
hevinci
6877900ac2 update download system 2023-09-27 16:31:24 +08:00
hevinci
45dbe2a0e6 update resource package 2023-09-27 16:31:16 +08:00
hevinci
4234885f94 update resource package 2023-09-27 12:04:11 +08:00
hevinci
bae55ca511 update operation system 2023-09-26 18:58:39 +08:00
hevinci
f804e8405e update settings 2023-09-25 18:40:02 +08:00
hevinci
3c9c61c346 update resource package 2023-09-25 18:37:58 +08:00
hevinci
d560d8a2e8 update asset bundle collector 2023-09-25 18:37:49 +08:00
hevinci
054ee93360 update asset bundle collector 2023-09-25 16:53:03 +08:00
hevinci
eb98eaeb3b update resource package 2023-09-25 16:30:24 +08:00
hevinci
8fe2fa7bc6 update operation system 2023-09-25 16:08:17 +08:00
hevinci
95894f92db update asset bundle collector 2023-09-25 14:43:17 +08:00
hevinci
61e06dee4c update yooasset2.0 2023-09-25 10:45:21 +08:00
hevinci
e207d834bd update yooasset2.0 2023-09-25 10:41:58 +08:00
hevinci
e358bbf46c update yooasset2.0 2023-09-21 17:23:31 +08:00
hevinci
9c0f9557e8 update yooasset2.0 2023-09-21 17:23:02 +08:00
hevinci
006d4c6f09 update yooasset2.0 2023-09-20 16:11:11 +08:00
hevinci
6fb5a4b946 update yooasset2.0 2023-09-20 16:10:57 +08:00
hevinci
6687d75090 update yooasset2.0 2023-09-20 16:10:37 +08:00
hevinci
01cf9ccd54 update yooasset2.0 2023-09-20 16:09:52 +08:00
何冠峰
880b6d429d Merge pull request #151 from michael811125/main
加入 ExtdBuildTasks 进行 SBP 扩展,修复 Sprite 打包冗馀问题 (猫佬方案) + typo error
2023-08-28 10:30:58 +08:00
MichaelO
070db961fc corrected typo error 2023-08-26 15:03:12 +08:00
MichaelO
96ef379668 Merge branch 'tuyoogame:main' into main 2023-08-25 20:48:08 +08:00
hevinci
697a87721f Update CHANGELOG.md 2023-08-25 20:39:53 +08:00
hevinci
09cf93d852 Update package.json 2023-08-25 20:39:46 +08:00
hevinci
8725821a27 update download system 2023-08-25 20:15:58 +08:00
MichaelO
7ad8651ca0 加入 ExtdBuildTasks 进行 SBP 扩展,修复 Sprite 打包冗馀问题 2023-08-25 19:48:02 +08:00
hevinci
a2e57c6e90 update operation system 2023-08-25 17:37:49 +08:00
hevinci
6d37bca2a9 update asset bundle builder 2023-08-25 17:37:34 +08:00
hevinci
8471bb0f9a update asset bundle builder
暂时移除xxHash
2023-08-25 17:19:57 +08:00
何冠峰
05cb57db09 Merge pull request #150 from yingnierxiao/main
优化打包速度,提示编辑器启动速度,md5替换xxhash,速度提升一倍以上
2023-08-25 15:17:49 +08:00
yingnierxiao
064e9a1aa3 优化打包速度,提示编辑器启动速度,md5替换xxhash,速度提升一倍以上 2023-08-25 14:53:59 +08:00
hevinci
a618b6cf9e update asset bundle reporter 2023-08-18 18:31:15 +08:00
何冠峰
e3e810e702 Merge pull request #134 from gepengmiss/main
bundle viewer 功能扩展
2023-08-18 17:58:43 +08:00
hevinci
b4f0d6bab8 fix #138 2023-08-18 17:40:55 +08:00
hevinci
44cb4168cf update asset bundle collector 2023-08-17 22:13:31 +08:00
hevinci
559ed95999 update asset bundle collector
增加在配置错误的时候警示提示。
2023-08-17 21:53:51 +08:00
hevinci
b766df1d31 update shader variant collector 2023-08-17 21:18:21 +08:00
hevinci
057ff6b22b fix #130 2023-08-17 21:05:21 +08:00
hevinci
995b0c8050 update space shooter 2023-08-15 18:19:07 +08:00
hevinci
a2d4691f04 update package system
IQueryServices接口变更为IBuildinQueryServices
2023-08-14 12:27:43 +08:00
hevinci
ab2d7d4724 update operation system
Operation状态增加Processing处理中状态
2023-08-11 16:20:38 +08:00
hevinci
9b4abf86b6 update runtime code
可寻址模式默认支持通过资源路径加载。
2023-08-09 20:15:55 +08:00
hevinci
0331b7b6e3 update editor code 2023-08-09 20:15:33 +08:00
hevinci
e31799e78b Update CHANGELOG.md 2023-07-28 17:32:44 +08:00
hevinci
a8405eea6d Update package.json 2023-07-28 17:32:38 +08:00
hevinci
c11f072c50 update asset system 2023-07-28 17:17:23 +08:00
YGP
bd080eb19b modify bundleViewer func 2023-07-27 16:12:21 +08:00
YGP
ef231e213e modify bundleViewer func 2023-07-27 16:06:09 +08:00
YGP
a5900b5f99 ignore 2023-07-27 16:04:59 +08:00
hevinci
b22bbd4e27 update editor code 2023-07-25 18:48:32 +08:00
hevinci
664866b627 update space shooter 2023-07-25 18:38:02 +08:00
hevinci
ad9bdc6574 update download system 2023-07-25 18:37:43 +08:00
hevinci
b93b993951 update package system 2023-07-20 14:28:22 +08:00
hevinci
cb2cb4e556 update package system 2023-07-20 11:27:56 +08:00
hevinci
ab32bd390d update space shooter 2023-07-20 11:08:52 +08:00
hevinci
b34374adfa update runtime code 2023-07-20 11:08:38 +08:00
hevinci
b53b6a4246 update runtime code 2023-07-20 11:08:28 +08:00
hevinci
191fbff768 update package system
增加对清单激活的检测
2023-07-19 18:18:03 +08:00
hevinci
e8a4ddf331 update runtime code 2023-07-19 17:48:26 +08:00
hevinci
aee6e2d2f8 update space shooter 2023-07-19 17:06:35 +08:00
hevinci
b737b20602 update runtime code
支持开发者资源分发和加载
2023-07-19 17:06:20 +08:00
hevinci
b5df539392 update package system
增加对UpdatePackageManifestOperation参数的检测
2023-07-19 15:57:34 +08:00
hevinci
36c53e5d94 update space shooter 2023-07-19 14:34:51 +08:00
hevinci
15ce6b8c8c update runtime code 2023-07-19 14:34:43 +08:00
hevinci
19aa82c131 update editor code 2023-07-19 11:22:59 +08:00
2217 changed files with 68030 additions and 115353 deletions

21
.gitignore vendored
View File

@@ -10,8 +10,26 @@
/[Ll]ogs/
/[Mm]emoryCaptures/
/Bundles/
/ProjectSettings/
/App/
/yoo/
/Assets/Docs
/Assets/Docs.meta
/Assets/StreamingAssets
/Assets/StreamingAssets.meta
/Assets/Samples
/Assets/Samples.meta
/Assets/csc.rsp
/Assets/csc.rsp.meta
/UserSettings
# Asset meta data should only be ignored when the corresponding asset is also ignored
!/[Aa]ssets/**/*.meta
# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*
@@ -54,6 +72,7 @@ sysinfo.txt
# Builds
*.apk
*.unitypackage
*.zip
# Crashlytics generated file
crashlytics-build.properties

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d6268d725eec21b4aae819adc1553f0e
guid: fab3cd742c11be2479b07f5d447a78c9
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -1,6 +1,5 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("YooAsset.Editor")]
// 外部友元
[assembly: InternalsVisibleTo("YooAsset.EditorExtension")]
[assembly: InternalsVisibleTo("YooAsset.RuntimeExtension")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 35749e57d9a3da84aa60c348bc6bbe9d
guid: ef774f01e50ab0a4d88122041938a6b9
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 58462a7dcef164e43878a037395d4417
guid: bdbb4647038dcc842802f546c2fedc83
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,670 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
public class AssetArtReporterWindow : EditorWindow
{
[MenuItem("YooAsset/AssetArt Reporter", false, 302)]
public static AssetArtReporterWindow OpenWindow()
{
AssetArtReporterWindow window = GetWindow<AssetArtReporterWindow>("AssetArt Reporter", true, WindowsDefine.DockedWindowTypes);
window.minSize = new Vector2(800, 600);
return window;
}
private class ElementTableData : DefaultTableData
{
public ReportElement Element;
}
private class PassesBtnCell : ITableCell, IComparable
{
public object CellValue { set; get; }
public string SearchTag { private set; get; }
public ReportElement Element
{
get
{
return (ReportElement)CellValue;
}
}
public PassesBtnCell(string searchTag, ReportElement element)
{
SearchTag = searchTag;
CellValue = element;
}
public object GetDisplayObject()
{
return string.Empty;
}
public int CompareTo(object other)
{
if (other is PassesBtnCell cell)
{
return this.Element.Passes.CompareTo(cell.Element.Passes);
}
else
{
return 0;
}
}
}
private class WhiteListBtnCell : ITableCell, IComparable
{
public object CellValue { set; get; }
public string SearchTag { private set; get; }
public ReportElement Element
{
get
{
return (ReportElement)CellValue;
}
}
public WhiteListBtnCell(string searchTag, ReportElement element)
{
SearchTag = searchTag;
CellValue = element;
}
public object GetDisplayObject()
{
return string.Empty;
}
public int CompareTo(object other)
{
if (other is WhiteListBtnCell cell)
{
return this.Element.IsWhiteList.CompareTo(cell.Element.IsWhiteList);
}
else
{
return 0;
}
}
}
private ToolbarSearchField _searchField;
private Button _showHiddenBtn;
private Button _whiteListVisibleBtn;
private Button _passesVisibleBtn;
private Label _titleLabel;
private Label _descLabel;
private TableViewer _elementTableView;
private ScanReportCombiner _reportCombiner;
private string _lastestOpenFolder;
private List<ITableData> _sourceDatas;
private bool _elementVisibleState = true;
private bool _whiteListVisibleState = true;
private bool _passesVisibleState = true;
public void CreateGUI()
{
try
{
VisualElement root = this.rootVisualElement;
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<AssetArtReporterWindow>();
if (visualAsset == null)
return;
visualAsset.CloneTree(root);
// 导入按钮
var importSingleBtn = root.Q<Button>("SingleImportButton");
importSingleBtn.clicked += ImportSingleBtn_clicked;
var importMultiBtn = root.Q<Button>("MultiImportButton");
importMultiBtn.clicked += ImportMultiBtn_clicked;
// 修复按钮
var fixAllBtn = root.Q<Button>("FixAllButton");
fixAllBtn.clicked += FixAllBtn_clicked;
var fixSelectBtn = root.Q<Button>("FixSelectButton");
fixSelectBtn.clicked += FixSelectBtn_clicked;
// 可见性按钮
_showHiddenBtn = root.Q<Button>("ShowHiddenButton");
_showHiddenBtn.clicked += ShowHiddenBtn_clicked;
_whiteListVisibleBtn = root.Q<Button>("WhiteListVisibleButton");
_whiteListVisibleBtn.clicked += WhiteListVisibleBtn_clicked;
_passesVisibleBtn = root.Q<Button>("PassesVisibleButton");
_passesVisibleBtn.clicked += PassesVsibleBtn_clicked;
// 文件导出按钮
var exportFilesBtn = root.Q<Button>("ExportFilesButton");
exportFilesBtn.clicked += ExportFilesBtn_clicked;
// 搜索过滤
_searchField = root.Q<ToolbarSearchField>("SearchField");
_searchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
// 标题和备注
_titleLabel = root.Q<Label>("ReportTitle");
_descLabel = root.Q<Label>("ReportDesc");
// 列表相关
_elementTableView = root.Q<TableViewer>("TopTableView");
_elementTableView.ClickTableDataEvent = OnClickTableViewItem;
_lastestOpenFolder = EditorTools.GetProjectPath();
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
}
public void OnDestroy()
{
if (_reportCombiner != null)
_reportCombiner.SaveChange();
}
/// <summary>
/// 导入单个报告文件
/// </summary>
public void ImportSingleReprotFile(string filePath)
{
// 记录本次打开目录
_lastestOpenFolder = Path.GetDirectoryName(filePath);
_reportCombiner = new ScanReportCombiner();
try
{
var scanReport = ScanReportConfig.ImportJsonConfig(filePath);
_reportCombiner.Combine(scanReport);
// 刷新页面
RefreshToolbar();
FillTableView();
RebuildView();
}
catch (System.Exception e)
{
_reportCombiner = null;
_titleLabel.text = "导入报告失败!";
_descLabel.text = e.Message;
UnityEngine.Debug.LogError(e.StackTrace);
}
}
/// <summary>
/// 导入单个报告对象
/// </summary>
public void ImportSingleReprotFile(ScanReport report)
{
_reportCombiner = new ScanReportCombiner();
try
{
_reportCombiner.Combine(report);
// 刷新页面
RefreshToolbar();
FillTableView();
RebuildView();
}
catch (System.Exception e)
{
_reportCombiner = null;
_titleLabel.text = "导入报告失败!";
_descLabel.text = e.Message;
UnityEngine.Debug.LogError(e.StackTrace);
}
}
private void ImportSingleBtn_clicked()
{
string selectFilePath = EditorUtility.OpenFilePanel("导入报告", _lastestOpenFolder, "json");
if (string.IsNullOrEmpty(selectFilePath))
return;
ImportSingleReprotFile(selectFilePath);
}
private void ImportMultiBtn_clicked()
{
string selectFolderPath = EditorUtility.OpenFolderPanel("导入报告", _lastestOpenFolder, null);
if (string.IsNullOrEmpty(selectFolderPath))
return;
// 记录本次打开目录
_lastestOpenFolder = selectFolderPath;
_reportCombiner = new ScanReportCombiner();
try
{
string[] files = Directory.GetFiles(selectFolderPath);
foreach (string filePath in files)
{
string extension = System.IO.Path.GetExtension(filePath);
if (extension == ".json")
{
var scanReport = ScanReportConfig.ImportJsonConfig(filePath);
_reportCombiner.Combine(scanReport);
}
}
// 刷新页面
RefreshToolbar();
FillTableView();
RebuildView();
}
catch (System.Exception e)
{
_reportCombiner = null;
_titleLabel.text = "Failed to import report!";
_descLabel.text = e.Message;
UnityEngine.Debug.LogError(e.StackTrace);
}
}
private void FixAllBtn_clicked()
{
if (EditorUtility.DisplayDialog("Info", "Fix all resources (excluding whitelist and hidden elements)", "Yes", "No"))
{
if (_reportCombiner != null)
_reportCombiner.FixAll();
}
}
private void FixSelectBtn_clicked()
{
if (EditorUtility.DisplayDialog("Info", "Fix selected resources (including whitelist and hidden elements)", "Yes", "No"))
{
if (_reportCombiner != null)
_reportCombiner.FixSelect();
}
}
private void ShowHiddenBtn_clicked()
{
_elementVisibleState = !_elementVisibleState;
RefreshToolbar();
RebuildView();
}
private void WhiteListVisibleBtn_clicked()
{
_whiteListVisibleState = !_whiteListVisibleState;
RefreshToolbar();
RebuildView();
}
private void PassesVsibleBtn_clicked()
{
_passesVisibleState = !_passesVisibleState;
RefreshToolbar();
RebuildView();
}
private void ExportFilesBtn_clicked()
{
string selectFolderPath = EditorUtility.OpenFolderPanel("Export all selected resources", EditorTools.GetProjectPath(), string.Empty);
if (string.IsNullOrEmpty(selectFolderPath) == false)
{
if (_reportCombiner != null)
_reportCombiner.ExportFiles(selectFolderPath);
}
}
private void RefreshToolbar()
{
if (_reportCombiner == null)
return;
_titleLabel.text = _reportCombiner.ReportTitle;
_descLabel.text = _reportCombiner.ReportDesc;
var enableColor = new Color32(18, 100, 18, 255);
var disableColor = new Color32(100, 100, 100, 255);
if (_elementVisibleState)
_showHiddenBtn.style.backgroundColor = new StyleColor(enableColor);
else
_showHiddenBtn.style.backgroundColor = new StyleColor(disableColor);
if (_whiteListVisibleState)
_whiteListVisibleBtn.style.backgroundColor = new StyleColor(enableColor);
else
_whiteListVisibleBtn.style.backgroundColor = new StyleColor(disableColor);
if (_passesVisibleState)
_passesVisibleBtn.style.backgroundColor = new StyleColor(enableColor);
else
_passesVisibleBtn.style.backgroundColor = new StyleColor(disableColor);
}
private void FillTableView()
{
if (_reportCombiner == null)
return;
_elementTableView.ClearAll(true, true);
// 眼睛标题
{
var columnStyle = new ColumnStyle(20);
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("眼睛框", string.Empty, columnStyle);
column.MakeCell = () =>
{
var toggle = new ToggleDisplay();
toggle.text = string.Empty;
toggle.style.unityTextAlign = TextAnchor.MiddleCenter;
toggle.RegisterValueChangedCallback((evt) => { OnDisplayToggleValueChange(toggle, evt); });
return toggle;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var toggle = element as ToggleDisplay;
toggle.userData = data;
var tableData = data as ElementTableData;
toggle.SetValueWithoutNotify(tableData.Element.Hidden);
};
_elementTableView.AddColumn(column);
var headerElement = _elementTableView.GetHeaderElement("眼睛框");
headerElement.style.unityTextAlign = TextAnchor.MiddleCenter;
}
// 通过标题
{
var columnStyle = new ColumnStyle(70);
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = true;
var column = new TableColumn("通过", "通过", columnStyle);
column.MakeCell = () =>
{
var button = new Button();
button.text = "通过";
button.style.unityTextAlign = TextAnchor.MiddleCenter;
button.SetEnabled(false);
return button;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
Button button = element as Button;
var elementTableData = data as ElementTableData;
if (elementTableData.Element.Passes)
{
button.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
button.text = "通过";
}
else
{
button.style.backgroundColor = new StyleColor(new Color32(137, 0, 0, 255));
button.text = "失败";
}
};
_elementTableView.AddColumn(column);
var headerElement = _elementTableView.GetHeaderElement("通过");
headerElement.style.unityTextAlign = TextAnchor.MiddleCenter;
}
// 白名单标题
{
var columnStyle = new ColumnStyle(70);
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = true;
var column = new TableColumn("白名单", "白名单", columnStyle);
column.MakeCell = () =>
{
Button button = new Button();
button.text = "白名单";
button.style.unityTextAlign = TextAnchor.MiddleCenter;
button.clickable.clickedWithEventInfo += OnClickWhitListButton;
return button;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
Button button = element as Button;
button.userData = data;
var elementTableData = data as ElementTableData;
if (elementTableData.Element.IsWhiteList)
button.style.backgroundColor = new StyleColor(new Color32(56, 147, 58, 255));
else
button.style.backgroundColor = new StyleColor(new Color32(100, 100, 100, 255));
};
_elementTableView.AddColumn(column);
var headerElement = _elementTableView.GetHeaderElement("白名单");
headerElement.style.unityTextAlign = TextAnchor.MiddleCenter;
}
// 选中标题
{
var columnStyle = new ColumnStyle(20);
columnStyle.Stretchable = false;
columnStyle.Searchable = false;
columnStyle.Sortable = false;
var column = new TableColumn("选中框", string.Empty, columnStyle);
column.MakeCell = () =>
{
var toggle = new Toggle();
toggle.text = string.Empty;
toggle.style.unityTextAlign = TextAnchor.MiddleCenter;
toggle.RegisterValueChangedCallback((evt) => { OnSelectToggleValueChange(toggle, evt); });
return toggle;
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var toggle = element as Toggle;
toggle.userData = data;
var tableData = data as ElementTableData;
toggle.SetValueWithoutNotify(tableData.Element.IsSelected);
};
_elementTableView.AddColumn(column);
}
// 自定义标题栏
foreach (var header in _reportCombiner.Headers)
{
var columnStyle = new ColumnStyle(header.Width, header.MinWidth, header.MaxWidth);
columnStyle.Stretchable = header.Stretchable;
columnStyle.Searchable = header.Searchable;
columnStyle.Sortable = header.Sortable;
columnStyle.Counter = header.Counter;
columnStyle.Units = header.Units;
var column = new TableColumn(header.HeaderTitle, header.HeaderTitle, columnStyle);
column.MakeCell = () =>
{
if (header.HeaderType == EHeaderType.AssetObject)
{
var objectFiled = new ObjectField();
return objectFiled;
}
else
{
var label = new Label();
label.style.marginLeft = 3f;
label.style.unityTextAlign = TextAnchor.MiddleLeft;
return label;
}
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
if (header.HeaderType == EHeaderType.AssetObject)
{
var objectFiled = element as ObjectField;
objectFiled.value = (UnityEngine.Object)cell.GetDisplayObject();
}
else
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
}
};
_elementTableView.AddColumn(column);
}
// 填充数据源
_sourceDatas = new List<ITableData>(_reportCombiner.Elements.Count);
foreach (var element in _reportCombiner.Elements)
{
var tableData = new ElementTableData();
tableData.Element = element;
// 固定标题
tableData.AddButtonCell("眼睛框");
tableData.AddCell(new PassesBtnCell("通过", element));
tableData.AddCell(new WhiteListBtnCell("白名单", element));
tableData.AddButtonCell("选中框");
// 自定义标题
foreach (var scanInfo in element.ScanInfos)
{
var header = _reportCombiner.GetHeader(scanInfo.HeaderTitle);
if (header.HeaderType == EHeaderType.AssetPath)
{
tableData.AddAssetPathCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.AssetObject)
{
tableData.AddAssetObjectCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.StringValue)
{
tableData.AddStringValueCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.LongValue)
{
long value = Convert.ToInt64(scanInfo.ScanInfo);
tableData.AddLongValueCell(scanInfo.HeaderTitle, value);
}
else if (header.HeaderType == EHeaderType.DoubleValue)
{
double value = Convert.ToDouble(scanInfo.ScanInfo);
tableData.AddDoubleValueCell(scanInfo.HeaderTitle, value);
}
else
{
throw new NotImplementedException(header.HeaderType.ToString());
}
}
_sourceDatas.Add(tableData);
}
_elementTableView.itemsSource = _sourceDatas;
}
private void RebuildView()
{
if (_reportCombiner == null)
return;
string searchKeyword = _searchField.value;
// 搜索匹配
DefaultSearchSystem.Search(_sourceDatas, searchKeyword);
// 开关匹配
foreach (var tableData in _sourceDatas)
{
var elementTableData = tableData as ElementTableData;
if (_elementVisibleState == false && elementTableData.Element.Hidden)
{
tableData.Visible = false;
continue;
}
if (_passesVisibleState == false && elementTableData.Element.Passes)
{
tableData.Visible = false;
continue;
}
if (_whiteListVisibleState == false && elementTableData.Element.IsWhiteList)
{
tableData.Visible = false;
continue;
}
}
// 重建视图
_elementTableView.RebuildView();
}
private void OnClickTableViewItem(PointerDownEvent evt, ITableData tableData)
{
// 双击后检视对应的资源
if (evt.clickCount == 2)
{
foreach (var cell in tableData.Cells)
{
if (cell is AssetPathCell assetPathCell)
{
if (assetPathCell.PingAssetObject())
break;
}
}
}
}
private void OnSearchKeyWordChange(ChangeEvent<string> e)
{
RebuildView();
}
private void OnSelectToggleValueChange(Toggle toggle, ChangeEvent<bool> e)
{
// 处理自身
toggle.SetValueWithoutNotify(e.newValue);
// 记录数据
var elementTableData = toggle.userData as ElementTableData;
elementTableData.Element.IsSelected = e.newValue;
// 处理多选目标
var selectedItems = _elementTableView.selectedItems;
foreach (var selectedItem in selectedItems)
{
var selectElement = selectedItem as ElementTableData;
selectElement.Element.IsSelected = e.newValue;
}
// 重绘视图
RebuildView();
}
private void OnDisplayToggleValueChange(ToggleDisplay toggle, ChangeEvent<bool> e)
{
// 处理自身
toggle.SetValueWithoutNotify(e.newValue);
// 记录数据
var elementTableData = toggle.userData as ElementTableData;
elementTableData.Element.Hidden = e.newValue;
// 处理多选目标
var selectedItems = _elementTableView.selectedItems;
foreach (var selectedItem in selectedItems)
{
var selectElement = selectedItem as ElementTableData;
if (selectElement != null)
selectElement.Element.Hidden = e.newValue;
}
// 重绘视图
RebuildView();
}
private void OnClickWhitListButton(EventBase evt)
{
// 刷新点击的按钮
Button button = evt.target as Button;
var elementTableData = button.userData as ElementTableData;
elementTableData.Element.IsWhiteList = !elementTableData.Element.IsWhiteList;
// 刷新框选的按钮
var selectedItems = _elementTableView.selectedItems;
if (selectedItems.Count() > 1)
{
foreach (var selectedItem in selectedItems)
{
var selectElement = selectedItem as ElementTableData;
selectElement.Element.IsWhiteList = selectElement.Element.IsWhiteList;
}
}
RebuildView();
}
}
}
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 24698266f028e4a47bb88f091fd64547
guid: 4048f85b9ff1f424a89a9d6109e6faaf
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,22 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row;">
<uie:ToolbarSearchField focusable="true" name="SearchField" style="flex-grow: 1;" />
<ui:Button text="Fix Select" display-tooltip-when-elided="true" name="FixSelectButton" style="width: 80px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Fix All" display-tooltip-when-elided="true" name="FixAllButton" style="width: 80px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Export Select" display-tooltip-when-elided="true" name="ExportFilesButton" style="width: 100px; background-color: rgb(56, 147, 58);" />
<ui:Button text=" Multi-Import" display-tooltip-when-elided="true" name="MultiImportButton" style="width: 100px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Import" display-tooltip-when-elided="true" name="SingleImportButton" style="width: 100px; background-color: rgb(56, 147, 58);" />
</uie:Toolbar>
<ui:VisualElement name="PublicContainer" style="background-color: rgb(79, 79, 79); flex-direction: column; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
<ui:Label text="标题" display-tooltip-when-elided="true" name="ReportTitle" style="height: 16px; -unity-font-style: bold; -unity-text-align: middle-center;" />
<ui:Label text="说明" display-tooltip-when-elided="true" name="ReportDesc" style="-unity-text-align: upper-left; -unity-font-style: bold; background-color: rgb(42, 42, 42); min-height: 50px; border-top-left-radius: 3px; border-bottom-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; white-space: normal;" />
</ui:VisualElement>
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row;">
<ui:Button text="显示隐藏元素" display-tooltip-when-elided="true" name="ShowHiddenButton" style="width: 100px;" />
<ui:Button text="显示通过元素" display-tooltip-when-elided="true" name="PassesVisibleButton" style="width: 100px;" />
<ui:Button text="显示白名单元素" display-tooltip-when-elided="true" name="WhiteListVisibleButton" style="width: 100px;" />
</uie:Toolbar>
<ui:VisualElement name="AssetGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<YooAsset.Editor.TableViewer name="TopTableView" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a5296d9c037ce3944b5c197cbdd78a8b
guid: b87fc70b750616849942173af3bdfd90
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}

View File

@@ -0,0 +1,31 @@

namespace YooAsset.Editor
{
public enum EHeaderType
{
/// <summary>
/// 资源路径
/// </summary>
AssetPath,
/// <summary>
/// 资源对象
/// </summary>
AssetObject,
/// <summary>
/// 字符串
/// </summary>
StringValue,
/// <summary>
/// 整数数值
/// </summary>
LongValue,
/// <summary>
/// 浮点数数值
/// </summary>
DoubleValue,
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7fbb7b27f54d3b0439a951348fd9d785
guid: 97cd7d0d616708e42bc53ed7d88718c9
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
[Serializable]
public class ReportElement
{
/// <summary>
/// GUID白名单存储对象
/// </summary>
public string GUID;
/// <summary>
/// 扫描是否通过
/// </summary>
public bool Passes = true;
/// <summary>
/// 反馈的信息列表
/// </summary>
public List<ReportScanInfo> ScanInfos = new List<ReportScanInfo>();
public ReportElement(string guid)
{
GUID = guid;
}
/// <summary>
/// 添加扫描信息
/// </summary>
public void AddScanInfo(string headerTitle, string value)
{
var reportScanInfo = new ReportScanInfo(headerTitle, value);
ScanInfos.Add(reportScanInfo);
}
/// <summary>
/// 添加扫描信息
/// </summary>
public void AddScanInfo(string headerTitle, long value)
{
AddScanInfo(headerTitle, value.ToString());
}
/// <summary>
/// 添加扫描信息
/// </summary>
public void AddScanInfo(string headerTitle, double value)
{
AddScanInfo(headerTitle, value.ToString());
}
/// <summary>
/// 获取扫描信息
/// </summary>
public ReportScanInfo GetScanInfo(string headerTitle)
{
foreach (var scanInfo in ScanInfos)
{
if (scanInfo.HeaderTitle == headerTitle)
return scanInfo;
}
UnityEngine.Debug.LogWarning($"Not found {nameof(ReportScanInfo)} : {headerTitle}");
return null;
}
#region
/// <summary>
/// 是否在列表里选中
/// </summary>
public bool IsSelected { set; get; }
/// <summary>
/// 是否在白名单里
/// </summary>
public bool IsWhiteList { set; get; }
/// <summary>
/// 是否隐藏元素
/// </summary>
public bool Hidden { set; get; }
#endregion
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: fe50795c51a46884088139b840c1557f
guid: d61f7ee1a8215bf438071055f0a9cb09
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,154 @@
using System;
using UnityEditor;
namespace YooAsset.Editor
{
[Serializable]
public class ReportHeader
{
public const int MaxValue = 8388608;
/// <summary>
/// 标题
/// </summary>
public string HeaderTitle;
/// <summary>
/// 标题宽度
/// </summary>
public int Width;
/// <summary>
/// 单元列最小宽度
/// </summary>
public int MinWidth = 50;
/// <summary>
/// 单元列最大宽度
/// </summary>
public int MaxWidth = MaxValue;
/// <summary>
/// 可伸缩选项
/// </summary>
public bool Stretchable = false;
/// <summary>
/// 可搜索选项
/// </summary>
public bool Searchable = false;
/// <summary>
/// 可排序选项
/// </summary>
public bool Sortable = false;
/// <summary>
/// 统计数量
/// </summary>
public bool Counter = false;
/// <summary>
/// 展示单位
/// </summary>
public string Units = string.Empty;
/// <summary>
/// 数值类型
/// </summary>
public EHeaderType HeaderType = EHeaderType.StringValue;
public ReportHeader(string headerTitle, int width)
{
HeaderTitle = headerTitle;
Width = width;
MinWidth = width;
MaxWidth = width;
}
public ReportHeader(string headerTitle, int width, int minWidth, int maxWidth)
{
HeaderTitle = headerTitle;
Width = width;
MinWidth = minWidth;
MaxWidth = maxWidth;
}
public ReportHeader SetMinWidth(int value)
{
MinWidth = value;
return this;
}
public ReportHeader SetMaxWidth(int value)
{
MaxWidth = value;
return this;
}
public ReportHeader SetStretchable()
{
Stretchable = true;
return this;
}
public ReportHeader SetSearchable()
{
Searchable = true;
return this;
}
public ReportHeader SetSortable()
{
Sortable = true;
return this;
}
public ReportHeader SetCounter()
{
Counter = true;
return this;
}
public ReportHeader SetUnits(string units)
{
Units = units;
return this;
}
public ReportHeader SetHeaderType(EHeaderType value)
{
HeaderType = value;
return this;
}
/// <summary>
/// 检测数值有效性
/// </summary>
public void CheckValueValid(string value)
{
if (HeaderType == EHeaderType.AssetPath)
{
string guid = AssetDatabase.AssetPathToGUID(value);
if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset path : {value}");
}
else if (HeaderType == EHeaderType.AssetObject)
{
string guid = AssetDatabase.AssetPathToGUID(value);
if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset object : {value}");
}
else if (HeaderType == EHeaderType.DoubleValue)
{
if (double.TryParse(value, out double doubleValue) == false)
throw new Exception($"{HeaderTitle} value is invalid double value : {value}");
}
else if (HeaderType == EHeaderType.LongValue)
{
if (long.TryParse(value, out long longValue) == false)
throw new Exception($"{HeaderTitle} value is invalid long value : {value}");
}
else if (HeaderType == EHeaderType.StringValue)
{
}
else
{
throw new System.NotImplementedException(HeaderType.ToString());
}
}
}
}

View File

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

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
[Serializable]
public class ReportScanInfo
{
/// <summary>
/// 标题
/// </summary>
public string HeaderTitle;
/// <summary>
/// 扫描反馈的信息
/// </summary>
public string ScanInfo;
public ReportScanInfo(string headerTitle, string scanInfo)
{
HeaderTitle = headerTitle;
ScanInfo = scanInfo;
}
}
}

View File

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

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
[Serializable]
public class ScanReport
{
/// <summary>
/// 文件签名(自动填写)
/// </summary>
public string FileSign;
/// <summary>
/// 文件版本(自动填写)
/// </summary>
public string FileVersion;
/// <summary>
/// 模式类型(自动填写)
/// </summary>
public string SchemaType;
/// <summary>
/// 扫描器GUID自动填写
/// </summary>
public string ScannerGUID;
/// <summary>
/// 报告名称
/// </summary>
public string ReportName;
/// <summary>
/// 报告介绍
/// </summary>
public string ReportDesc;
/// <summary>
/// 报告的标题列表
/// </summary>
public List<ReportHeader> ReportHeaders = new List<ReportHeader>();
/// <summary>
/// 扫描的元素列表
/// </summary>
public List<ReportElement> ReportElements = new List<ReportElement>();
public ScanReport(string reportName, string reportDesc)
{
ReportName = reportName;
ReportDesc = reportDesc;
}
/// <summary>
/// 添加标题
/// </summary>
public ReportHeader AddHeader(string headerTitle, int width)
{
var reportHeader = new ReportHeader(headerTitle, width);
ReportHeaders.Add(reportHeader);
return reportHeader;
}
/// <summary>
/// 添加标题
/// </summary>
public ReportHeader AddHeader(string headerTitle, int width, int minWidth, int maxWidth)
{
var reportHeader = new ReportHeader(headerTitle, width, minWidth, maxWidth);
ReportHeaders.Add(reportHeader);
return reportHeader;
}
/// <summary>
/// 检测错误
/// </summary>
public void CheckError()
{
// 检测标题
Dictionary<string, ReportHeader> headerMap = new Dictionary<string, ReportHeader>();
foreach (var header in ReportHeaders)
{
string headerTitle = header.HeaderTitle;
if (headerMap.ContainsKey(headerTitle))
throw new Exception($"The header title {headerTitle} already exists !");
else
headerMap.Add(headerTitle, header);
}
// 检测扫描元素
HashSet<string> elementMap = new HashSet<string>();
foreach (var element in ReportElements)
{
if (string.IsNullOrEmpty(element.GUID))
throw new Exception($"The report element GUID is null or empty !");
if (elementMap.Contains(element.GUID))
throw new Exception($"The report element GUID already exists ! {element.GUID}");
else
elementMap.Add(element.GUID);
foreach (var scanInfo in element.ScanInfos)
{
if (headerMap.ContainsKey(scanInfo.HeaderTitle) == false)
throw new Exception($"The report element header {scanInfo.HeaderTitle} is missing !");
// 检测数值有效性
var header = headerMap[scanInfo.HeaderTitle];
header.CheckValueValid(scanInfo.ScanInfo);
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,221 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
/// <summary>
/// 资源扫描报告合并器
/// 说明:相同类型的报告可以合并查看
/// </summary>
public class ScanReportCombiner
{
/// <summary>
/// 模式类型
/// </summary>
public string SchemaType { private set; get; }
/// <summary>
/// 报告标题
/// </summary>
public string ReportTitle { private set; get; }
/// <summary>
/// 报告介绍
/// </summary>
public string ReportDesc { private set; get; }
/// <summary>
/// 标题列表
/// </summary>
public List<ReportHeader> Headers = new List<ReportHeader>();
/// <summary>
/// 扫描结果
/// </summary>
public readonly List<ReportElement> Elements = new List<ReportElement>(10000);
private readonly Dictionary<string, ScanReport> _combines = new Dictionary<string, ScanReport>(100);
/// <summary>
/// 合并报告文件
/// 注意:模式不同的报告文件会合并失败!
/// </summary>
public bool Combine(ScanReport scanReport)
{
if (string.IsNullOrEmpty(scanReport.SchemaType))
{
Debug.LogError("Scan report schema type is null or empty !");
return false;
}
if (string.IsNullOrEmpty(SchemaType))
{
SchemaType = scanReport.SchemaType;
ReportTitle = scanReport.ReportName;
ReportDesc = scanReport.ReportDesc;
Headers = scanReport.ReportHeaders;
}
if (SchemaType != scanReport.SchemaType)
{
Debug.LogWarning($"Scan report has different schema type{scanReport.SchemaType} != {SchemaType}");
return false;
}
if (_combines.ContainsKey(scanReport.ScannerGUID))
{
Debug.LogWarning($"Scan report has already existed : {scanReport.ScannerGUID}");
return false;
}
_combines.Add(scanReport.ScannerGUID, scanReport);
CombineInternal(scanReport);
return true;
}
private void CombineInternal(ScanReport scanReport)
{
string scannerGUID = scanReport.ScannerGUID;
List<ReportElement> elements = scanReport.ReportElements;
// 设置白名单
var scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null)
{
foreach (var element in elements)
{
if (scanner.CheckWhiteList(element.GUID))
element.IsWhiteList = true;
}
}
// 添加到集合
Elements.AddRange(elements);
}
/// <summary>
/// 获取指定的标题类
/// </summary>
public ReportHeader GetHeader(string headerTitle)
{
foreach (var header in Headers)
{
if (header.HeaderTitle == headerTitle)
return header;
}
UnityEngine.Debug.LogWarning($"Not found {nameof(ReportHeader)} : {headerTitle}");
return null;
}
/// <summary>
/// 导出选中文件
/// </summary>
public void ExportFiles(string exportFolderPath)
{
if (string.IsNullOrEmpty(exportFolderPath))
return;
foreach (var element in Elements)
{
if (element.IsSelected)
{
string assetPath = AssetDatabase.GUIDToAssetPath(element.GUID);
if (string.IsNullOrEmpty(assetPath) == false)
{
string destPath = Path.Combine(exportFolderPath, assetPath);
EditorTools.CopyFile(assetPath, destPath, true);
}
}
}
}
/// <summary>
/// 保存改变数据
/// </summary>
public void SaveChange()
{
// 存储白名单
foreach (var scanReport in _combines.Values)
{
string scannerGUID = scanReport.ScannerGUID;
var elements = scanReport.ReportElements;
var scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null)
{
List<string> whiteList = new List<string>(elements.Count);
foreach (var element in elements)
{
if (element.IsWhiteList)
whiteList.Add(element.GUID);
}
whiteList.Sort();
scanner.WhiteList = whiteList;
AssetArtScannerSettingData.SaveFile();
}
}
}
/// <summary>
/// 修复所有元素
/// 注意:排除白名单和隐藏元素
/// </summary>
public void FixAll()
{
foreach (var scanReport in _combines.Values)
{
string scannerGUID = scanReport.ScannerGUID;
var elements = scanReport.ReportElements;
List<ReportElement> fixList = new List<ReportElement>(elements.Count);
foreach (var element in elements)
{
if (element.Passes || element.IsWhiteList || element.Hidden)
continue;
fixList.Add(element);
}
FixInternal(scannerGUID, fixList);
}
}
/// <summary>
/// 修复选定元素
/// 注意:包含白名单和隐藏元素
/// </summary>
public void FixSelect()
{
foreach (var scanReport in _combines.Values)
{
string scannerGUID = scanReport.ScannerGUID;
var elements = scanReport.ReportElements;
List<ReportElement> fixList = new List<ReportElement>(elements.Count);
foreach (var element in elements)
{
if (element.Passes)
continue;
if (element.IsSelected)
fixList.Add(element);
}
FixInternal(scannerGUID, fixList);
}
}
private void FixInternal(string scannerGUID, List<ReportElement> fixList)
{
AssetArtScanner scanner = AssetArtScannerSettingData.Setting.GetScanner(scannerGUID);
if (scanner != null)
{
var schema = scanner.LoadSchema();
if (schema != null)
{
schema.FixResult(fixList);
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,54 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine;
namespace YooAsset.Editor
{
public class ScanReportConfig
{
/// <summary>
/// 导入JSON报告文件
/// </summary>
public static ScanReport ImportJsonConfig(string filePath)
{
if (File.Exists(filePath) == false)
throw new FileNotFoundException(filePath);
string jsonData = FileUtility.ReadAllText(filePath);
ScanReport report = JsonUtility.FromJson<ScanReport>(jsonData);
// 检测配置文件的签名
if (report.FileSign != ScannerDefine.ReportFileSign)
throw new Exception($"导入的报告文件无法识别 : {filePath}");
// 检测报告文件的版本
if (report.FileVersion != ScannerDefine.ReportFileVersion)
throw new Exception($"报告文件的版本不匹配 : {report.FileVersion} != {ScannerDefine.ReportFileVersion}");
// 检测标题数和内容是否匹配
foreach (var element in report.ReportElements)
{
if (element.ScanInfos.Count != report.ReportHeaders.Count)
{
throw new Exception($"报告的标题数和内容不匹配!");
}
}
return report;
}
/// <summary>
/// 导出JSON报告文件
/// </summary>
public static void ExportJsonConfig(string savePath, ScanReport scanReport)
{
if (File.Exists(savePath))
File.Delete(savePath);
string json = JsonUtility.ToJson(scanReport, true);
FileUtility.WriteAllText(savePath, json);
}
}
}

View File

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

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 96a75a20111d6124696665e7aac3564c
guid: 9bc1ecc3b72dfc34782fb6926d679f92
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,13 @@
using System;
namespace YooAsset.Editor
{
[Serializable]
public class AssetArtCollector
{
/// <summary>
/// 扫描目录
/// </summary>
public string CollectPath = string.Empty;
}
}

View File

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

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
[Serializable]
public class AssetArtScanner
{
/// <summary>
/// 扫描器GUID
/// </summary>
public string ScannerGUID = string.Empty;
/// <summary>
/// 扫描器名称
/// </summary>
public string ScannerName = string.Empty;
/// <summary>
/// 扫描器描述
/// </summary>
public string ScannerDesc = string.Empty;
/// <summary>
/// 扫描模式
/// 注意文件路径或文件GUID
/// </summary>
public string ScannerSchema = string.Empty;
/// <summary>
/// 存储目录
/// </summary>
public string SaveDirectory = string.Empty;
/// <summary>
/// 收集列表
/// </summary>
public List<AssetArtCollector> Collectors = new List<AssetArtCollector>();
/// <summary>
/// 白名单
/// </summary>
public List<string> WhiteList = new List<string>();
/// <summary>
/// 检测关键字匹配
/// </summary>
public bool CheckKeyword(string keyword)
{
if (ScannerName.Contains(keyword) || ScannerDesc.Contains(keyword))
return true;
else
return false;
}
/// <summary>
/// 是否在白名单里
/// </summary>
public bool CheckWhiteList(string guid)
{
return WhiteList.Contains(guid);
}
/// <summary>
/// 检测配置错误
/// </summary>
public void CheckConfigError()
{
if (string.IsNullOrEmpty(ScannerName))
throw new Exception($"Scanner name is null or empty !");
if (string.IsNullOrEmpty(ScannerSchema))
throw new Exception($"Scanner {ScannerName} schema is null !");
if (string.IsNullOrEmpty(SaveDirectory) == false)
{
if (Directory.Exists(SaveDirectory) == false)
throw new Exception($"Scanner {ScannerName} save directory is invalid : {SaveDirectory}");
}
}
/// <summary>
/// 加载扫描模式实例
/// </summary>
public ScannerSchema LoadSchema()
{
if (string.IsNullOrEmpty(ScannerSchema))
return null;
string filePath;
if (ScannerSchema.StartsWith("Assets/"))
{
filePath = ScannerSchema;
}
else
{
string guid = ScannerSchema;
filePath = AssetDatabase.GUIDToAssetPath(guid);
}
var schema = AssetDatabase.LoadMainAssetAtPath(filePath) as ScannerSchema;
if (schema == null)
Debug.LogWarning($"Failed load scanner schema : {filePath}");
return schema;
}
/// <summary>
/// 运行扫描器生成报告类
/// </summary>
public ScanReport RunScanner()
{
if (Collectors.Count == 0)
Debug.LogWarning($"Scanner {ScannerName} collector is empty !");
ScannerSchema schema = LoadSchema();
if (schema == null)
throw new Exception($"Failed to load schema : {ScannerSchema}");
var report = schema.RunScanner(this);
report.FileSign = ScannerDefine.ReportFileSign;
report.FileVersion = ScannerDefine.ReportFileVersion;
report.SchemaType = schema.GetType().FullName;
report.ScannerGUID = ScannerGUID;
return report;
}
}
}

View File

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

View File

@@ -0,0 +1,85 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class AssetArtScannerConfig
{
public class ConfigWrapper
{
/// <summary>
/// 文件签名
/// </summary>
public string FileSign;
/// <summary>
/// 文件版本
/// </summary>
public string FileVersion;
/// <summary>
/// 扫描器列表
/// </summary>
public List<AssetArtScanner> Scanners = new List<AssetArtScanner>();
}
/// <summary>
/// 导入JSON配置文件
/// </summary>
public static void ImportJsonConfig(string filePath)
{
if (File.Exists(filePath) == false)
throw new FileNotFoundException(filePath);
string json = FileUtility.ReadAllText(filePath);
ConfigWrapper setting = JsonUtility.FromJson<ConfigWrapper>(json);
// 检测配置文件的签名
if (setting.FileSign != ScannerDefine.SettingFileSign)
throw new Exception($"导入的配置文件无法识别 : {filePath}");
// 检测配置文件的版本
if (setting.FileVersion != ScannerDefine.SettingFileVersion)
throw new Exception($"配置文件的版本不匹配 : {setting.FileVersion} != {ScannerDefine.SettingFileVersion}");
// 检测配置合法性
HashSet<string> scanGUIDs = new HashSet<string>();
foreach (var sacnner in setting.Scanners)
{
if (scanGUIDs.Contains(sacnner.ScannerGUID))
{
throw new Exception($"Scanner {sacnner.ScannerName} GUID is existed : {sacnner.ScannerGUID} ");
}
else
{
scanGUIDs.Add(sacnner.ScannerGUID);
}
}
AssetArtScannerSettingData.Setting.Scanners = setting.Scanners;
AssetArtScannerSettingData.SaveFile();
}
/// <summary>
/// 导出JSON配置文件
/// </summary>
public static void ExportJsonConfig(string savePath)
{
if (File.Exists(savePath))
File.Delete(savePath);
ConfigWrapper wrapper = new ConfigWrapper();
wrapper.FileSign = ScannerDefine.SettingFileSign;
wrapper.FileVersion = ScannerDefine.SettingFileVersion;
wrapper.Scanners = AssetArtScannerSettingData.Setting.Scanners;
string json = JsonUtility.ToJson(wrapper, true);
FileUtility.WriteAllText(savePath, json);
}
}
}

View File

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

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEngine;
using NUnit.Framework.Constraints;
namespace YooAsset.Editor
{
public class AssetArtScannerSetting : ScriptableObject
{
/// <summary>
/// 扫描器列表
/// </summary>
public List<AssetArtScanner> Scanners = new List<AssetArtScanner>();
/// <summary>
/// 开始扫描
/// </summary>
public ScannerResult BeginScan(string scannerGUID)
{
try
{
// 获取扫描器配置
var scanner = GetScanner(scannerGUID);
if (scanner == null)
throw new Exception($"Invalid scanner GUID : {scannerGUID}");
// 检测配置合法性
scanner.CheckConfigError();
// 开始扫描工作
ScanReport report = scanner.RunScanner();
report.CheckError();
// 返回扫描结果
return new ScannerResult(report);
}
catch (Exception e)
{
return new ScannerResult(e.Message, e.StackTrace);
}
}
/// <summary>
/// 获取指定的扫描器
/// </summary>
public AssetArtScanner GetScanner(string scannerGUID)
{
foreach (var scanner in Scanners)
{
if (scanner.ScannerGUID == scannerGUID)
return scanner;
}
Debug.LogWarning($"Not found scanner : {scannerGUID}");
return null;
}
}
}

View File

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

View File

@@ -0,0 +1,161 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class AssetArtScannerSettingData
{
/// <summary>
/// 配置数据是否被修改
/// </summary>
public static bool IsDirty { private set; get; } = false;
static AssetArtScannerSettingData()
{
}
private static AssetArtScannerSetting _setting = null;
public static AssetArtScannerSetting Setting
{
get
{
if (_setting == null)
_setting = SettingLoader.LoadSettingData<AssetArtScannerSetting>();
return _setting;
}
}
/// <summary>
/// 存储配置文件
/// </summary>
public static void SaveFile()
{
if (Setting != null)
{
IsDirty = false;
EditorUtility.SetDirty(Setting);
AssetDatabase.SaveAssets();
Debug.Log($"{nameof(AssetArtScannerSetting)}.asset is saved!");
}
}
/// <summary>
/// 清空所有数据
/// </summary>
public static void ClearAll()
{
Setting.Scanners.Clear();
SaveFile();
}
/// <summary>
/// 扫描所有项
/// </summary>
public static void ScanAll()
{
foreach (var scanner in Setting.Scanners)
{
var scanResult = Setting.BeginScan(scanner.ScannerGUID);
if (scanResult.Succeed == false)
{
Debug.LogError($"{scanner.ScannerName} failed : {scanResult.ErrorInfo}");
}
}
}
/// <summary>
/// 扫描所有项
/// </summary>
public static void ScanAll(string keyword)
{
foreach (var scanner in Setting.Scanners)
{
if (string.IsNullOrEmpty(keyword) == false)
{
if (scanner.CheckKeyword(keyword) == false)
continue;
}
var scanResult = Setting.BeginScan(scanner.ScannerGUID);
if (scanResult.Succeed == false)
{
Debug.LogError($"{scanner.ScannerName} failed : {scanResult.ErrorInfo}");
}
}
}
/// <summary>
/// 扫描单项
/// </summary>
public static ScannerResult Scan(string scannerGUID)
{
var scanResult = Setting.BeginScan(scannerGUID);
if (scanResult.Succeed == false)
{
Debug.LogError(scanResult.ErrorInfo);
}
return scanResult;
}
// 扫描器编辑相关
public static AssetArtScanner CreateScanner(string name, string desc)
{
AssetArtScanner scanner = new AssetArtScanner();
scanner.ScannerGUID = System.Guid.NewGuid().ToString();
scanner.ScannerName = name;
scanner.ScannerDesc = desc;
Setting.Scanners.Add(scanner);
IsDirty = true;
return scanner;
}
public static void RemoveScanner(AssetArtScanner scanner)
{
if (Setting.Scanners.Remove(scanner))
{
IsDirty = true;
}
else
{
Debug.LogWarning($"Failed remove scanner : {scanner.ScannerName}");
}
}
public static void ModifyScanner(AssetArtScanner scanner)
{
if (scanner != null)
{
IsDirty = true;
}
}
// 资源收集编辑相关
public static void CreateCollector(AssetArtScanner scanner, AssetArtCollector collector)
{
scanner.Collectors.Add(collector);
IsDirty = true;
}
public static void RemoveCollector(AssetArtScanner scanner, AssetArtCollector collector)
{
if (scanner.Collectors.Remove(collector))
{
IsDirty = true;
}
else
{
Debug.LogWarning($"Failed remove collector : {collector.CollectPath}");
}
}
public static void ModifyCollector(AssetArtScanner scanner, AssetArtCollector collector)
{
if (scanner != null && collector != null)
{
IsDirty = true;
}
}
}
}

View File

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

View File

@@ -0,0 +1,549 @@
#if UNITY_2019_4_OR_NEWER
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
public class AssetArtScannerWindow : EditorWindow
{
[MenuItem("YooAsset/AssetArt Scanner", false, 301)]
public static void OpenWindow()
{
AssetArtScannerWindow window = GetWindow<AssetArtScannerWindow>("AssetArt Scanner", true, WindowsDefine.DockedWindowTypes);
window.minSize = new Vector2(800, 600);
}
private Button _saveButton;
private ListView _scannerListView;
private ToolbarSearchField _scannerSearchField;
private VisualElement _scannerContentContainer;
private VisualElement _inspectorContainer;
private Label _schemaGuideTxt;
private TextField _scannerNameTxt;
private TextField _scannerDescTxt;
private ObjectField _scannerSchemaField;
private ObjectField _outputFolderField;
private ScrollView _collectorScrollView;
private int _lastModifyScannerIndex = 0;
public void CreateGUI()
{
Undo.undoRedoPerformed -= RefreshWindow;
Undo.undoRedoPerformed += RefreshWindow;
try
{
VisualElement root = this.rootVisualElement;
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<AssetArtScannerWindow>();
if (visualAsset == null)
return;
visualAsset.CloneTree(root);
// 导入导出按钮
var exportBtn = root.Q<Button>("ExportButton");
exportBtn.clicked += ExportBtn_clicked;
var importBtn = root.Q<Button>("ImportButton");
importBtn.clicked += ImportBtn_clicked;
// 配置保存按钮
_saveButton = root.Q<Button>("SaveButton");
_saveButton.clicked += SaveBtn_clicked;
// 扫描按钮
var scanAllBtn = root.Q<Button>("ScanAllButton");
scanAllBtn.clicked += ScanAllBtn_clicked;
var scanBtn = root.Q<Button>("ScanBtn");
scanBtn.clicked += ScanBtn_clicked;
// 扫描列表相关
_scannerListView = root.Q<ListView>("ScannerListView");
_scannerListView.makeItem = MakeScannerListViewItem;
_scannerListView.bindItem = BindScannerListViewItem;
#if UNITY_2022_3_OR_NEWER
_scannerListView.selectionChanged += ScannerListView_onSelectionChange;
#elif UNITY_2020_1_OR_NEWER
_scannerListView.onSelectionChange += ScannerListView_onSelectionChange;
#else
_scannerListView.onSelectionChanged += ScannerListView_onSelectionChange;
#endif
// 扫描列表过滤
_scannerSearchField = root.Q<ToolbarSearchField>("ScannerSearchField");
_scannerSearchField.RegisterValueChangedCallback(OnSearchKeyWordChange);
// 扫描器添加删除按钮
var scannerAddContainer = root.Q("ScannerAddContainer");
{
var addBtn = scannerAddContainer.Q<Button>("AddBtn");
addBtn.clicked += AddScannerBtn_clicked;
var removeBtn = scannerAddContainer.Q<Button>("RemoveBtn");
removeBtn.clicked += RemoveScannerBtn_clicked;
}
// 扫描器容器
_scannerContentContainer = root.Q("ScannerContentContainer");
// 检视界面容器
_inspectorContainer = root.Q("InspectorContainer");
// 扫描器指南
_schemaGuideTxt = root.Q<Label>("SchemaUserGuide");
// 扫描器名称
_scannerNameTxt = root.Q<TextField>("ScannerName");
_scannerNameTxt.RegisterValueChangedCallback(evt =>
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner != null)
{
selectScanner.ScannerName = evt.newValue;
AssetArtScannerSettingData.ModifyScanner(selectScanner);
FillScannerListViewData();
}
});
// 扫描器备注
_scannerDescTxt = root.Q<TextField>("ScannerDesc");
_scannerDescTxt.RegisterValueChangedCallback(evt =>
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner != null)
{
selectScanner.ScannerDesc = evt.newValue;
AssetArtScannerSettingData.ModifyScanner(selectScanner);
FillScannerListViewData();
}
});
// 扫描模式
_scannerSchemaField = root.Q<ObjectField>("ScanSchema");
_scannerSchemaField.RegisterValueChangedCallback(evt =>
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner != null)
{
string assetPath = AssetDatabase.GetAssetPath(evt.newValue);
selectScanner.ScannerSchema = AssetDatabase.AssetPathToGUID(assetPath);
AssetArtScannerSettingData.ModifyScanner(selectScanner);
}
});
// 存储目录
_outputFolderField = root.Q<ObjectField>("OutputFolder");
_outputFolderField.RegisterValueChangedCallback(evt =>
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner != null)
{
if (evt.newValue == null)
{
selectScanner.SaveDirectory = string.Empty;
AssetArtScannerSettingData.ModifyScanner(selectScanner);
}
else
{
string assetPath = AssetDatabase.GetAssetPath(evt.newValue);
if (AssetDatabase.IsValidFolder(assetPath))
{
selectScanner.SaveDirectory = assetPath;
AssetArtScannerSettingData.ModifyScanner(selectScanner);
}
else
{
Debug.LogWarning($"Select asset object not folder ! {assetPath}");
}
}
}
});
// 收集列表相关
_collectorScrollView = root.Q<ScrollView>("CollectorScrollView");
_collectorScrollView.style.height = new Length(100, LengthUnit.Percent);
_collectorScrollView.viewDataKey = "scrollView";
// 收集器创建按钮
var collectorAddContainer = root.Q("CollectorAddContainer");
{
var addBtn = collectorAddContainer.Q<Button>("AddBtn");
addBtn.clicked += AddCollectorBtn_clicked;
}
// 刷新窗体
RefreshWindow();
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
}
public void OnDestroy()
{
// 注意:清空所有撤销操作
Undo.ClearAll();
if (AssetArtScannerSettingData.IsDirty)
AssetArtScannerSettingData.SaveFile();
}
public void Update()
{
if (_saveButton != null)
{
if (AssetArtScannerSettingData.IsDirty)
{
if (_saveButton.enabledSelf == false)
_saveButton.SetEnabled(true);
}
else
{
if (_saveButton.enabledSelf)
_saveButton.SetEnabled(false);
}
}
}
private void RefreshWindow()
{
_scannerContentContainer.visible = false;
FillScannerListViewData();
}
private void ExportBtn_clicked()
{
string resultPath = EditorTools.OpenFolderPanel("Export JSON", "Assets/");
if (resultPath != null)
{
AssetArtScannerConfig.ExportJsonConfig($"{resultPath}/AssetArtScannerConfig.json");
}
}
private void ImportBtn_clicked()
{
string resultPath = EditorTools.OpenFilePath("Import JSON", "Assets/", "json");
if (resultPath != null)
{
AssetArtScannerConfig.ImportJsonConfig(resultPath);
RefreshWindow();
}
}
private void SaveBtn_clicked()
{
AssetArtScannerSettingData.SaveFile();
}
private void ScanAllBtn_clicked()
{
if (EditorUtility.DisplayDialog("Info", $"Start full scan!", "Yes", "No"))
{
string searchKeyWord = _scannerSearchField.value;
AssetArtScannerSettingData.ScanAll(searchKeyWord);
AssetDatabase.Refresh();
}
else
{
Debug.LogWarning("Full scan has been canceled.");
}
}
private void ScanBtn_clicked()
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner == null)
return;
ScannerResult scannerResult = AssetArtScannerSettingData.Scan(selectScanner.ScannerGUID);
if (scannerResult.Succeed)
{
// 自动打开报告界面
scannerResult.OpenReportWindow();
AssetDatabase.Refresh();
}
}
private void OnSearchKeyWordChange(ChangeEvent<string> e)
{
_lastModifyScannerIndex = 0;
RefreshWindow();
}
// 分组列表相关
private void FillScannerListViewData()
{
_scannerListView.Clear();
_scannerListView.ClearSelection();
var filterItems = FilterScanners();
if (AssetArtScannerSettingData.Setting.Scanners.Count == filterItems.Count)
{
#if UNITY_2020_3_OR_NEWER
_scannerListView.reorderable = true;
#endif
_scannerListView.itemsSource = AssetArtScannerSettingData.Setting.Scanners;
_scannerListView.Rebuild();
}
else
{
#if UNITY_2020_3_OR_NEWER
_scannerListView.reorderable = false;
#endif
_scannerListView.itemsSource = filterItems;
_scannerListView.Rebuild();
}
if (_lastModifyScannerIndex >= 0 && _lastModifyScannerIndex < _scannerListView.itemsSource.Count)
{
_scannerListView.selectedIndex = _lastModifyScannerIndex;
}
}
private List<AssetArtScanner> FilterScanners()
{
string searchKeyWord = _scannerSearchField.value;
List<AssetArtScanner> result = new List<AssetArtScanner>(AssetArtScannerSettingData.Setting.Scanners.Count);
// 过滤列表
foreach (var scanner in AssetArtScannerSettingData.Setting.Scanners)
{
if (string.IsNullOrEmpty(searchKeyWord) == false)
{
if (scanner.CheckKeyword(searchKeyWord) == false)
continue;
}
result.Add(scanner);
}
return result;
}
private VisualElement MakeScannerListViewItem()
{
VisualElement element = new VisualElement();
{
var label = new Label();
label.name = "Label1";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.flexGrow = 1f;
label.style.height = 20f;
element.Add(label);
}
return element;
}
private void BindScannerListViewItem(VisualElement element, int index)
{
List<AssetArtScanner> sourceList = _scannerListView.itemsSource as List<AssetArtScanner>;
var scanner = sourceList[index];
var textField1 = element.Q<Label>("Label1");
if (string.IsNullOrEmpty(scanner.ScannerDesc))
textField1.text = scanner.ScannerName;
else
textField1.text = $"{scanner.ScannerName} ({scanner.ScannerDesc})";
}
private void ScannerListView_onSelectionChange(IEnumerable<object> objs)
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner == null)
{
_scannerContentContainer.visible = false;
return;
}
_scannerContentContainer.visible = true;
_lastModifyScannerIndex = _scannerListView.selectedIndex;
_scannerNameTxt.SetValueWithoutNotify(selectScanner.ScannerName);
_scannerDescTxt.SetValueWithoutNotify(selectScanner.ScannerDesc);
// 显示检视面板
var scanSchema = selectScanner.LoadSchema();
RefreshInspector(scanSchema);
// 设置Schema对象
if (scanSchema == null)
{
_scannerSchemaField.SetValueWithoutNotify(null);
_schemaGuideTxt.text = string.Empty;
}
else
{
_scannerSchemaField.SetValueWithoutNotify(scanSchema);
_schemaGuideTxt.text = scanSchema.GetUserGuide();
}
// 显示存储目录
DefaultAsset saveFolder = AssetDatabase.LoadAssetAtPath<DefaultAsset>(selectScanner.SaveDirectory);
if (saveFolder == null)
{
_outputFolderField.SetValueWithoutNotify(null);
}
else
{
_outputFolderField.SetValueWithoutNotify(saveFolder);
}
FillCollectorViewData();
}
private void AddScannerBtn_clicked()
{
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow AddScanner");
AssetArtScannerSettingData.CreateScanner("Default Scanner", string.Empty);
FillScannerListViewData();
}
private void RemoveScannerBtn_clicked()
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner == null)
return;
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow RemoveScanner");
AssetArtScannerSettingData.RemoveScanner(selectScanner);
FillScannerListViewData();
}
// 收集列表相关
private void FillCollectorViewData()
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner == null)
return;
// 填充数据
_collectorScrollView.Clear();
for (int i = 0; i < selectScanner.Collectors.Count; i++)
{
VisualElement element = MakeCollectorListViewItem();
BindCollectorListViewItem(element, i);
_collectorScrollView.Add(element);
}
}
private VisualElement MakeCollectorListViewItem()
{
VisualElement element = new VisualElement();
VisualElement elementTop = new VisualElement();
elementTop.style.flexDirection = FlexDirection.Row;
element.Add(elementTop);
VisualElement elementSpace = new VisualElement();
elementSpace.style.flexDirection = FlexDirection.Column;
element.Add(elementSpace);
// Top VisualElement
{
var button = new Button();
button.name = "Button1";
button.text = "-";
button.style.unityTextAlign = TextAnchor.MiddleCenter;
button.style.flexGrow = 0f;
elementTop.Add(button);
}
{
var objectField = new ObjectField();
objectField.name = "ObjectField1";
objectField.label = "Collector";
objectField.objectType = typeof(UnityEngine.Object);
objectField.style.unityTextAlign = TextAnchor.MiddleLeft;
objectField.style.flexGrow = 1f;
elementTop.Add(objectField);
var label = objectField.Q<Label>();
label.style.minWidth = 63;
}
// Space VisualElement
{
var label = new Label();
label.style.height = 10;
elementSpace.Add(label);
}
return element;
}
private void BindCollectorListViewItem(VisualElement element, int index)
{
var selectScanner = _scannerListView.selectedItem as AssetArtScanner;
if (selectScanner == null)
return;
var collector = selectScanner.Collectors[index];
var collectObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(collector.CollectPath);
if (collectObject != null)
collectObject.name = collector.CollectPath;
// Remove Button
var removeBtn = element.Q<Button>("Button1");
removeBtn.clicked += () =>
{
RemoveCollectorBtn_clicked(collector);
};
// Collector Path
var objectField1 = element.Q<ObjectField>("ObjectField1");
objectField1.SetValueWithoutNotify(collectObject);
objectField1.RegisterValueChangedCallback(evt =>
{
collector.CollectPath = AssetDatabase.GetAssetPath(evt.newValue);
objectField1.value.name = collector.CollectPath;
AssetArtScannerSettingData.ModifyCollector(selectScanner, collector);
});
}
private void AddCollectorBtn_clicked()
{
var selectSacnner = _scannerListView.selectedItem as AssetArtScanner;
if (selectSacnner == null)
return;
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow AddCollector");
AssetArtCollector collector = new AssetArtCollector();
AssetArtScannerSettingData.CreateCollector(selectSacnner, collector);
FillCollectorViewData();
}
private void RemoveCollectorBtn_clicked(AssetArtCollector selectCollector)
{
var selectSacnner = _scannerListView.selectedItem as AssetArtScanner;
if (selectSacnner == null)
return;
if (selectCollector == null)
return;
Undo.RecordObject(AssetArtScannerSettingData.Setting, "YooAsset.AssetArtScannerWindow RemoveCollector");
AssetArtScannerSettingData.RemoveCollector(selectSacnner, selectCollector);
FillCollectorViewData();
}
// 属性面板相关
private void RefreshInspector(ScannerSchema scanSchema)
{
if (scanSchema == null)
{
UIElementsTools.SetElementVisible(_inspectorContainer, false);
return;
}
var inspector = scanSchema.CreateInspector();
if (inspector == null)
{
UIElementsTools.SetElementVisible(_inspectorContainer, false);
return;
}
if (inspector.Containner is VisualElement container)
{
UIElementsTools.SetElementVisible(_inspectorContainer, true);
_inspectorContainer.Clear();
_inspectorContainer.Add(container);
_inspectorContainer.style.width = inspector.Width;
_inspectorContainer.style.minWidth = inspector.MinWidth;
_inspectorContainer.style.maxWidth = inspector.MaxWidth;
}
else
{
Debug.LogWarning($"{nameof(ScannerSchema)} inspector container is invalid !");
UIElementsTools.SetElementVisible(_inspectorContainer, false);
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,33 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;">
<ui:Button text="Save" display-tooltip-when-elided="true" name="SaveButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Export" display-tooltip-when-elided="true" name="ExportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Import" display-tooltip-when-elided="true" name="ImportButton" style="width: 50px; background-color: rgb(56, 147, 58);" />
<ui:Button text="Scan All" display-tooltip-when-elided="true" name="ScanAllButton" style="width: 80px; background-color: rgb(56, 147, 58);" />
</uie:Toolbar>
<ui:VisualElement name="ContentContainer" style="flex-grow: 1; flex-direction: row;">
<ui:VisualElement name="ScannerListContainer" style="width: 250px; flex-grow: 0; background-color: rgb(67, 67, 67); border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px;">
<ui:Label text="Scanner List" display-tooltip-when-elided="true" name="ScannerListTitle" style="background-color: rgb(89, 89, 89); -unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 3px; border-right-width: 3px; border-top-width: 3px; border-bottom-width: 3px; font-size: 12px;" />
<uie:ToolbarSearchField focusable="true" name="ScannerSearchField" style="width: 230px;" />
<ui:ListView focusable="true" name="ScannerListView" item-height="20" virtualization-method="DynamicHeight" reorder-mode="Animated" reorderable="true" style="flex-grow: 1;" />
<ui:VisualElement name="ScannerAddContainer" style="justify-content: center; flex-direction: row; flex-shrink: 0;">
<ui:Button text=" - " display-tooltip-when-elided="true" name="RemoveBtn" />
<ui:Button text=" + " display-tooltip-when-elided="true" name="AddBtn" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="ScannerContentContainer" style="flex-grow: 1; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; min-width: 400px;">
<ui:Label text="Scanner" display-tooltip-when-elided="true" name="ScannerContentTitle" style="-unity-text-align: upper-center; -unity-font-style: bold; font-size: 12px; border-top-width: 3px; border-right-width: 3px; border-bottom-width: 3px; border-left-width: 3px; background-color: rgb(89, 89, 89);" />
<ui:Label display-tooltip-when-elided="true" name="SchemaUserGuide" style="-unity-text-align: upper-center; -unity-font-style: bold; border-left-width: 5px; border-right-width: 5px; border-top-width: 5px; border-bottom-width: 5px; font-size: 12px; height: 40px;" />
<ui:TextField picking-mode="Ignore" label="Scanner Name" name="ScannerName" />
<ui:TextField picking-mode="Ignore" label="Scanner Desc" name="ScannerDesc" />
<uie:ObjectField label="Scanner Schema" name="ScanSchema" type="YooAsset.Editor.ScannerSchema, YooAsset.Editor" allow-scene-objects="false" />
<uie:ObjectField label="Output Folder" name="OutputFolder" type="UnityEditor.DefaultAsset, UnityEditor.CoreModule" allow-scene-objects="false" />
<ui:VisualElement name="CollectorAddContainer" style="height: 20px; flex-direction: row-reverse;">
<ui:Button text="[ + ]" display-tooltip-when-elided="true" name="AddBtn" />
<ui:Button text="Scan" display-tooltip-when-elided="true" name="ScanBtn" style="width: 60px;" />
</ui:VisualElement>
<ui:ScrollView name="CollectorScrollView" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:VisualElement name="InspectorContainer" style="flex-grow: 1; border-top-width: 5px; border-right-width: 5px; border-bottom-width: 5px; border-left-width: 5px; background-color: rgb(67, 67, 67);" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5bbb873a7bee2924a86c876b67bb2cb4
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,26 @@

namespace YooAsset.Editor
{
public class ScannerDefine
{
/// <summary>
/// 报告文件签名
/// </summary>
public const string ReportFileSign = "596f6f4172745265706f7274";
/// <summary>
/// 配置文件签名
/// </summary>
public const string SettingFileSign = "596f6f41727453657474696e67";
/// <summary>
/// 报告文件的版本
/// </summary>
public const string ReportFileVersion = "1.0";
/// <summary>
/// 配置文件的版本
/// </summary>
public const string SettingFileVersion = "1.0";
}
}

View File

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

View File

@@ -0,0 +1,72 @@

namespace YooAsset.Editor
{
public class ScannerResult
{
/// <summary>
/// 报告对象
/// </summary>
public ScanReport Report { private set; get; }
/// <summary>
/// 错误信息
/// </summary>
public string ErrorInfo { private set; get; }
/// <summary>
/// 错误堆栈
/// </summary>
public string ErrorStack { private set; get; }
/// <summary>
/// 是否成功
/// </summary>
public bool Succeed
{
get
{
if (string.IsNullOrEmpty(ErrorInfo))
return true;
else
return false;
}
}
public ScannerResult(string error, string stack)
{
ErrorInfo = error;
ErrorStack = stack;
}
public ScannerResult(ScanReport report)
{
Report = report;
}
/// <summary>
/// 打开报告窗口
/// </summary>
public void OpenReportWindow()
{
if (Succeed)
{
var reproterWindow = AssetArtReporterWindow.OpenWindow();
reproterWindow.ImportSingleReprotFile(Report);
}
}
/// <summary>
/// 保存报告文件
/// </summary>
public void SaveReportFile(string saveDirectory)
{
if (Report == null)
throw new System.Exception("Scan report is invalid !");
if (string.IsNullOrEmpty(saveDirectory))
saveDirectory = "Assets/";
string filePath = $"{saveDirectory}/{Report.ReportName}_{Report.ReportDesc}.json";
ScanReportConfig.ExportJsonConfig(filePath, Report);
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace YooAsset.Editor
{
public abstract class ScannerSchema : ScriptableObject
{
/// <summary>
/// 获取用户指南信息
/// </summary>
public abstract string GetUserGuide();
/// <summary>
/// 运行生成扫描报告
/// </summary>
public abstract ScanReport RunScanner(AssetArtScanner scanner);
/// <summary>
/// 修复扫描结果
/// </summary>
public abstract void FixResult(List<ReportElement> fixList);
/// <summary>
/// 创建检视面板
/// </summary>
public virtual SchemaInspector CreateInspector()
{
return null;
}
}
}

View File

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

View File

@@ -0,0 +1,45 @@

namespace YooAsset.Editor
{
public class SchemaInspector
{
/// <summary>
/// 检视界面的UI元素容器UIElements元素
/// </summary>
public object Containner { private set; get; }
/// <summary>
/// 检视界面宽度
/// </summary>
public int Width = 250;
/// <summary>
/// 检视界面最小宽度
/// </summary>
public int MinWidth = 250;
/// <summary>
/// 检视界面最大宽度
/// </summary>
public int MaxWidth = 250;
public SchemaInspector(object containner)
{
Containner = containner;
}
public SchemaInspector(object containner, int width)
{
Containner = containner;
Width = width;
MinWidth = width;
MaxWidth = width;
}
public SchemaInspector(object containner, int width, int minWidth, int maxWidth)
{
Containner = containner;
Width = width;
MinWidth = minWidth;
MaxWidth = maxWidth;
}
}
}

View File

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

View File

@@ -8,105 +8,53 @@ using UnityEditor;
namespace YooAsset.Editor
{
public class AssetBundleBuilder
{
private readonly BuildContext _buildContext = new BuildContext();
public class AssetBundleBuilder
{
private readonly BuildContext _buildContext = new BuildContext();
/// <summary>
/// 构建资源包
/// </summary>
public BuildResult Run(BuildParameters buildParameters, List<IBuildTask> buildPipeline)
{
// 检测构建参数是否为空
if (buildParameters == null)
throw new Exception($"{nameof(buildParameters)} is null !");
/// <summary>
/// 构建资源包
/// </summary>
public BuildResult Run(BuildParameters buildParameters, List<IBuildTask> buildPipeline, bool enableLog)
{
// 检测构建参数是否为空
if (buildParameters == null)
throw new Exception($"{nameof(buildParameters)} is null !");
// 检测构建参数是否为空
if (buildPipeline.Count == 0)
throw new Exception($"Build pipeline is empty !");
// 检测构建参数是否为空
if (buildPipeline.Count == 0)
throw new Exception($"Build pipeline is empty !");
// 清空旧数据
_buildContext.ClearAllContext();
// 清空旧数据
_buildContext.ClearAllContext();
// 构建参数
var buildParametersContext = new BuildParametersContext(buildParameters);
_buildContext.SetContextObject(buildParametersContext);
// 构建参数
var buildParametersContext = new BuildParametersContext(buildParameters);
_buildContext.SetContextObject(buildParametersContext);
// 初始化日志
BuildLogger.InitLogger(buildParameters.EnableLog);
// 初始化日志系统
string logFilePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/buildInfo.log";
BuildLogger.InitLogger(enableLog, logFilePath);
// 执行构建流程
var buildResult = BuildRunner.Run(buildPipeline, _buildContext);
if (buildResult.Success)
{
buildResult.OutputPackageDirectory = buildParametersContext.GetPackageOutputDirectory();
BuildLogger.Log($"{buildParameters.BuildMode} pipeline build succeed !");
}
else
{
BuildLogger.Warning($"{buildParameters.BuildMode} pipeline build failed !");
BuildLogger.Error($"Build task failed : {buildResult.FailedTask}");
BuildLogger.Error(buildResult.ErrorInfo);
}
// 执行构建流程
BuildLogger.Log($"Begin to build package : {buildParameters.PackageName} by {buildParameters.BuildPipeline}");
var buildResult = BuildRunner.Run(buildPipeline, _buildContext);
if (buildResult.Success)
{
buildResult.OutputPackageDirectory = buildParametersContext.GetPackageOutputDirectory();
BuildLogger.Log("Resource pipeline build success");
}
else
{
BuildLogger.Error($"{buildParameters.BuildPipeline} build failed !");
BuildLogger.Error($"An error occurred in build task {buildResult.FailedTask}");
BuildLogger.Error(buildResult.ErrorInfo);
}
return buildResult;
}
// 关闭日志系统
BuildLogger.Shuntdown();
/// <summary>
/// 构建资源包
/// </summary>
public BuildResult Run(BuildParameters buildParameters)
{
var buildPipeline = GetDefaultBuildPipeline(buildParameters.BuildPipeline);
return Run(buildParameters, buildPipeline);
}
/// <summary>
/// 获取默认的构建流程
/// </summary>
private List<IBuildTask> GetDefaultBuildPipeline(EBuildPipeline buildPipeline)
{
// 获取任务节点的属性集合
if (buildPipeline == EBuildPipeline.BuiltinBuildPipeline)
{
List<IBuildTask> pipeline = new List<IBuildTask>
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding(), //开始执行构建
new TaskCopyRawFile(), //拷贝原生文件
new TaskVerifyBuildResult(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskUpdateBundleInfo(), //更新资源包信息
new TaskCreateManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件
new TaskCreatePackage(), //制作包裹
new TaskCopyBuildinFiles(), //拷贝内置文件
};
return pipeline;
}
else if (buildPipeline == EBuildPipeline.ScriptableBuildPipeline)
{
List<IBuildTask> pipeline = new List<IBuildTask>
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding_SBP(), //开始执行构建
new TaskCopyRawFile(), //拷贝原生文件
new TaskVerifyBuildResult_SBP(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskUpdateBundleInfo(), //更新补丁信息
new TaskCreateManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件
new TaskCreatePackage(), //制作补丁包
new TaskCopyBuildinFiles(), //拷贝内置文件
};
return pipeline;
}
else
{
throw new NotImplementedException();
}
}
}
return buildResult;
}
}
}

View File

@@ -6,23 +6,23 @@ using UnityEditor;
namespace YooAsset.Editor
{
public static class AssetBundleBuilderHelper
{
/// <summary>
/// 获取默认的输出根
/// </summary>
public static string GetDefaultBuildOutputRoot()
{
string projectPath = EditorTools.GetProjectPath();
return $"{projectPath}/Bundles";
}
public static class AssetBundleBuilderHelper
{
/// <summary>
/// 获取默认的输出根
/// </summary>
public static string GetDefaultBuildOutputRoot()
{
string projectPath = EditorTools.GetProjectPath();
return $"{projectPath}/Bundles";
}
/// <summary>
/// 获取流文件夹路径
/// </summary>
public static string GetDefaultStreamingAssetsRoot()
{
return $"{Application.dataPath}/StreamingAssets/{YooAssetSettings.DefaultYooFolderName}/";
}
}
/// <summary>
/// 获取流文件夹路径
/// </summary>
public static string GetStreamingAssetsRoot()
{
return YooAssetSettingsData.GetYooDefaultBuildinRoot();
}
}
}

View File

@@ -1,49 +1,130 @@
using System;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
[CreateAssetMenu(fileName = "AssetBundleBuilderSetting", menuName = "YooAsset/Create AssetBundle Builder Settings")]
public class AssetBundleBuilderSetting : ScriptableObject
{
/// <summary>
/// 构建管线
/// </summary>
public EBuildPipeline BuildPipeline = EBuildPipeline.BuiltinBuildPipeline;
public static class AssetBundleBuilderSetting
{
// BuildPipelineName
public static string GetPackageBuildPipeline(string packageName)
{
string key = $"{Application.productName}_{packageName}_BuildPipelineName";
string defaultValue = EBuildPipeline.ScriptableBuildPipeline.ToString();
return EditorPrefs.GetString(key, defaultValue);
}
public static void SetPackageBuildPipeline(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_BuildPipelineName";
EditorPrefs.SetString(key, buildPipeline);
}
/// <summary>
/// 构建模式
/// </summary>
public EBuildMode BuildMode = EBuildMode.ForceRebuild;
// ECompressOption
public static ECompressOption GetPackageCompressOption(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
return (ECompressOption)EditorPrefs.GetInt(key, (int)ECompressOption.LZ4);
}
public static void SetPackageCompressOption(string packageName, string buildPipeline, ECompressOption compressOption)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
EditorPrefs.SetInt(key, (int)compressOption);
}
/// <summary>
/// 构建的包裹名称
/// </summary>
public string BuildPackage = string.Empty;
// EFileNameStyle
public static EFileNameStyle GetPackageFileNameStyle(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
return (EFileNameStyle)EditorPrefs.GetInt(key, (int)EFileNameStyle.HashName);
}
public static void SetPackageFileNameStyle(string packageName, string buildPipeline, EFileNameStyle fileNameStyle)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
EditorPrefs.SetInt(key, (int)fileNameStyle);
}
/// <summary>
/// 压缩方式
/// </summary>
public ECompressOption CompressOption = ECompressOption.LZ4;
// EBuildinFileCopyOption
public static EBuildinFileCopyOption GetPackageBuildinFileCopyOption(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
return (EBuildinFileCopyOption)EditorPrefs.GetInt(key, (int)EBuildinFileCopyOption.None);
}
public static void SetPackageBuildinFileCopyOption(string packageName, string buildPipeline, EBuildinFileCopyOption buildinFileCopyOption)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
EditorPrefs.SetInt(key, (int)buildinFileCopyOption);
}
/// <summary>
/// 输出文件名称样式
/// </summary>
public EOutputNameStyle OutputNameStyle = EOutputNameStyle.HashName;
// BuildFileCopyParams
public static string GetPackageBuildinFileCopyParams(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
return EditorPrefs.GetString(key, string.Empty);
}
public static void SetPackageBuildinFileCopyParams(string packageName, string buildPipeline, string buildinFileCopyParams)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
EditorPrefs.SetString(key, buildinFileCopyParams);
}
/// <summary>
/// 首包资源文件的拷贝方式
/// </summary>
public ECopyBuildinFileOption CopyBuildinFileOption = ECopyBuildinFileOption.None;
// EncyptionServicesClassName
public static string GetPackageEncyptionServicesClassName(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(EncryptionNone).FullName}");
}
public static void SetPackageEncyptionServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionServicesClassName";
EditorPrefs.SetString(key, encyptionClassName);
}
/// <summary>
/// 首包资源文件的标签集合
/// </summary>
public string CopyBuildinFileTags = string.Empty;
// ManifestProcessServicesClassName
public static string GetPackageManifestProcessServicesClassName(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestProcessServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(ManifestProcessNone).FullName}");
}
public static void SetPackageManifestProcessServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestProcessServicesClassName";
EditorPrefs.SetString(key, encyptionClassName);
}
/// <summary>
/// 加密类名称
/// </summary>
public string EncyptionClassName = string.Empty;
}
// ManifestRestoreServicesClassName
public static string GetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestRestoreServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(ManifestRestoreNone).FullName}");
}
public static void SetPackageManifestRestoreServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestRestoreServicesClassName";
EditorPrefs.SetString(key, encyptionClassName);
}
// ClearBuildCache
public static bool GetPackageClearBuildCache(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ClearBuildCache";
return EditorPrefs.GetInt(key, 0) > 0;
}
public static void SetPackageClearBuildCache(string packageName, string buildPipeline, bool clearBuildCache)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ClearBuildCache";
EditorPrefs.SetInt(key, clearBuildCache ? 1 : 0);
}
// UseAssetDependencyDB
public static bool GetPackageUseAssetDependencyDB(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_UseAssetDependencyDB";
return EditorPrefs.GetInt(key, 0) > 0;
}
public static void SetPackageUseAssetDependencyDB(string packageName, string buildPipeline, bool useAssetDependencyDB)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_UseAssetDependencyDB";
EditorPrefs.SetInt(key, useAssetDependencyDB ? 1 : 0);
}
}
}

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class AssetBundleBuilderSettingData
{
private static AssetBundleBuilderSetting _setting = null;
public static AssetBundleBuilderSetting Setting
{
get
{
if (_setting == null)
LoadSettingData();
return _setting;
}
}
/// <summary>
/// 配置数据是否被修改
/// </summary>
public static bool IsDirty { set; get; } = false;
/// <summary>
/// 加载配置文件
/// </summary>
private static void LoadSettingData()
{
_setting = SettingLoader.LoadSettingData<AssetBundleBuilderSetting>();
}
/// <summary>
/// 存储文件
/// </summary>
public static void SaveFile()
{
if (Setting != null)
{
IsDirty = false;
EditorUtility.SetDirty(Setting);
AssetDatabase.SaveAssets();
Debug.Log($"{nameof(AssetBundleBuilderSetting)}.asset is saved!");
}
}
}
}

View File

@@ -1,215 +0,0 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
namespace YooAsset.Editor
{
public static class AssetBundleBuilderTools
{
/// <summary>
/// 检测所有损坏的预制体文件
/// </summary>
public static void CheckCorruptionPrefab(List<string> searchDirectorys)
{
if (searchDirectorys.Count == 0)
throw new Exception("路径列表不能为空!");
// 获取所有资源列表
int checkCount = 0;
int invalidCount = 0;
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Prefab, searchDirectorys.ToArray());
foreach (string assetPath in findAssets)
{
UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object));
if (prefab == null)
{
invalidCount++;
Debug.LogError($"发现损坏预制件:{assetPath}");
}
EditorTools.DisplayProgressBar("检测预制件文件是否损坏", ++checkCount, findAssets.Length);
}
EditorTools.ClearProgressBar();
if (invalidCount == 0)
Debug.Log($"没有发现损坏预制件");
}
/// <summary>
/// 检测所有动画控制器的冗余状态
/// </summary>
public static void FindRedundantAnimationState(List<string> searchDirectorys)
{
if (searchDirectorys.Count == 0)
throw new Exception("路径列表不能为空!");
// 获取所有资源列表
int checkCount = 0;
int findCount = 0;
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.RuntimeAnimatorController, searchDirectorys.ToArray());
foreach (string assetPath in findAssets)
{
AnimatorController animator= AssetDatabase.LoadAssetAtPath<AnimatorController>(assetPath);
if (FindRedundantAnimationState(animator))
{
findCount++;
Debug.LogWarning($"发现冗余的动画控制器:{assetPath}");
}
EditorTools.DisplayProgressBar("检测冗余的动画控制器", ++checkCount, findAssets.Length);
}
EditorTools.ClearProgressBar();
if (findCount == 0)
Debug.Log($"没有发现冗余的动画控制器");
else
AssetDatabase.SaveAssets();
}
/// <summary>
/// 清理所有材质球的冗余属性
/// </summary>
public static void ClearMaterialUnusedProperty(List<string> searchDirectorys)
{
if (searchDirectorys.Count == 0)
throw new Exception("路径列表不能为空!");
// 获取所有资源列表
int checkCount = 0;
int removedCount = 0;
string[] findAssets = EditorTools.FindAssets(EAssetSearchType.Material, searchDirectorys.ToArray());
foreach (string assetPath in findAssets)
{
Material mat = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
if (ClearMaterialUnusedProperty(mat))
{
removedCount++;
Debug.LogWarning($"材质球已被处理:{assetPath}");
}
EditorTools.DisplayProgressBar("清理冗余的材质球", ++checkCount, findAssets.Length);
}
EditorTools.ClearProgressBar();
if (removedCount == 0)
Debug.Log($"没有发现冗余的材质球");
else
AssetDatabase.SaveAssets();
}
/// <summary>
/// 清理无用的材质球属性
/// </summary>
private static bool ClearMaterialUnusedProperty(Material mat)
{
bool removeUnused = false;
SerializedObject so = new SerializedObject(mat);
SerializedProperty sp = so.FindProperty("m_SavedProperties");
sp.Next(true);
do
{
if (sp.isArray == false)
continue;
for (int i = sp.arraySize - 1; i >= 0; --i)
{
var p1 = sp.GetArrayElementAtIndex(i);
if (p1.isArray)
{
for (int ii = p1.arraySize - 1; ii >= 0; --ii)
{
var p2 = p1.GetArrayElementAtIndex(ii);
var val = p2.FindPropertyRelative("first");
if (mat.HasProperty(val.stringValue) == false)
{
Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
p1.DeleteArrayElementAtIndex(ii);
removeUnused = true;
}
}
}
else
{
var val = p1.FindPropertyRelative("first");
if (mat.HasProperty(val.stringValue) == false)
{
Debug.Log($"Material {mat.name} remove unused property : {val.stringValue}");
sp.DeleteArrayElementAtIndex(i);
removeUnused = true;
}
}
}
}
while (sp.Next(false));
so.ApplyModifiedProperties();
return removeUnused;
}
/// <summary>
/// 查找动画控制器里冗余的动画状态机
/// </summary>
private static bool FindRedundantAnimationState(AnimatorController animatorController)
{
if (animatorController == null)
return false;
string assetPath = AssetDatabase.GetAssetPath(animatorController);
// 查找使用的状态机名称
List<string> usedStateNames = new List<string>();
foreach (var layer in animatorController.layers)
{
foreach (var state in layer.stateMachine.states)
{
usedStateNames.Add(state.state.name);
}
}
List<string> allLines = new List<string>();
List<int> stateIndexList = new List<int>();
using (StreamReader reader = File.OpenText(assetPath))
{
string content;
while (null != (content = reader.ReadLine()))
{
allLines.Add(content);
if (content.StartsWith("AnimatorState:"))
{
stateIndexList.Add(allLines.Count - 1);
}
}
}
List<string> allStateNames = new List<string>();
foreach (var index in stateIndexList)
{
for (int i = index; i < allLines.Count; i++)
{
string content = allLines[i];
content = content.Trim();
if (content.StartsWith("m_Name"))
{
string[] splits = content.Split(':');
string name = splits[1].TrimStart(' '); //移除前面的空格
allStateNames.Add(name);
break;
}
}
}
bool foundRedundantState = false;
foreach (var stateName in allStateNames)
{
if (usedStateNames.Contains(stateName) == false)
{
Debug.LogWarning($"发现冗余的动画文件:{assetPath}={stateName}");
foundRedundantState = true;
}
}
return foundRedundantState;
}
}
}

View File

@@ -9,351 +9,166 @@ using UnityEngine.UIElements;
namespace YooAsset.Editor
{
public class AssetBundleBuilderWindow : EditorWindow
{
[MenuItem("YooAsset/AssetBundle Builder", false, 102)]
public static void OpenWindow()
{
AssetBundleBuilderWindow window = GetWindow<AssetBundleBuilderWindow>("资源包构建工具", true, WindowsDefine.DockedWindowTypes);
window.minSize = new Vector2(800, 600);
}
public class AssetBundleBuilderWindow : EditorWindow
{
[MenuItem("YooAsset/AssetBundle Builder", false, 102)]
public static void OpenWindow()
{
AssetBundleBuilderWindow window = GetWindow<AssetBundleBuilderWindow>("AssetBundle Builder", true, WindowsDefine.DockedWindowTypes);
window.minSize = new Vector2(800, 600);
}
private BuildTarget _buildTarget;
private List<Type> _encryptionServicesClassTypes;
private List<string> _encryptionServicesClassNames;
private List<string> _buildPackageNames;
private string _buildPackage;
private string _buildPipeline;
private Button _saveButton;
private TextField _buildOutputField;
private EnumField _buildPipelineField;
private EnumField _buildModeField;
private TextField _buildVersionField;
private PopupField<string> _buildPackageField;
private PopupField<string> _encryptionField;
private EnumField _compressionField;
private EnumField _outputNameStyleField;
private EnumField _copyBuildinFileOptionField;
private TextField _copyBuildinFileTagsField;
private Dictionary<string, Type> _viewClassDic = new Dictionary<string, Type>(10);
public void CreateGUI()
{
try
{
VisualElement root = this.rootVisualElement;
private Toolbar _toolbar;
private ToolbarMenu _packageMenu;
private ToolbarMenu _pipelineMenu;
private VisualElement _container;
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<AssetBundleBuilderWindow>();
if (visualAsset == null)
return;
visualAsset.CloneTree(root);
public void CreateGUI()
{
try
{
VisualElement root = this.rootVisualElement;
// 配置保存按钮
_saveButton = root.Q<Button>("SaveButton");
_saveButton.clicked += SaveBtn_clicked;
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<AssetBundleBuilderWindow>();
if (visualAsset == null)
return;
// 构建平台
_buildTarget = EditorUserBuildSettings.activeBuildTarget;
visualAsset.CloneTree(root);
_toolbar = root.Q<Toolbar>("Toolbar");
_container = root.Q("Container");
// 包裹名称列表
_buildPackageNames = GetBuildPackageNames();
// 检测构建包裹
var packageNames = GetBuildPackageNames();
if (packageNames.Count == 0)
{
var label = new Label();
label.text = "Not found any package";
label.style.width = 100;
_toolbar.Add(label);
return;
}
// 加密服务类
_encryptionServicesClassTypes = GetEncryptionServicesClassTypes();
_encryptionServicesClassNames = _encryptionServicesClassTypes.Select(t => t.Name).ToList();
// 构建包裹
{
_buildPackage = packageNames[0];
_packageMenu = new ToolbarMenu();
_packageMenu.style.width = 200;
foreach (var packageName in packageNames)
{
_packageMenu.menu.AppendAction(packageName, PackageMenuAction, PackageMenuFun, packageName);
}
_toolbar.Add(_packageMenu);
}
// 输出目录
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
_buildOutputField = root.Q<TextField>("BuildOutput");
_buildOutputField.SetValueWithoutNotify(defaultOutputRoot);
_buildOutputField.SetEnabled(false);
// 构建管线
{
_pipelineMenu = new ToolbarMenu();
_pipelineMenu.style.width = 200;
_toolbar.Add(_pipelineMenu);
// 构建管线
_buildPipelineField = root.Q<EnumField>("BuildPipeline");
_buildPipelineField.Init(AssetBundleBuilderSettingData.Setting.BuildPipeline);
_buildPipelineField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.BuildPipeline);
_buildPipelineField.style.width = 350;
_buildPipelineField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildPipeline = (EBuildPipeline)_buildPipelineField.value;
RefreshWindow();
});
var viewerClassTypes = EditorTools.GetAssignableTypes(typeof(BuildPipelineViewerBase));
foreach (var classType in viewerClassTypes)
{
var buildPipelineAttribute = EditorTools.GetAttribute<BuildPipelineAttribute>(classType);
if (buildPipelineAttribute == null)
{
Debug.LogWarning($"The class {classType.FullName} need attribute {nameof(BuildPipelineAttribute)}");
continue;
}
// 构建模式
_buildModeField = root.Q<EnumField>("BuildMode");
_buildModeField.Init(AssetBundleBuilderSettingData.Setting.BuildMode);
_buildModeField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.BuildMode);
_buildModeField.style.width = 350;
_buildModeField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildMode = (EBuildMode)_buildModeField.value;
RefreshWindow();
});
string pipelineName = buildPipelineAttribute.PipelineName;
if (_viewClassDic.ContainsKey(pipelineName))
{
Debug.LogWarning($"The pipeline has already exist : {pipelineName}");
}
else
{
_viewClassDic.Add(pipelineName, classType);
_pipelineMenu.menu.AppendAction(pipelineName, PipelineMenuAction, PipelineMenuFun);
}
}
}
// 构建版本
_buildVersionField = root.Q<TextField>("BuildVersion");
_buildVersionField.SetValueWithoutNotify(GetBuildPackageVersion());
RefreshBuildPipelineView();
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
// 构建包裹
var buildPackageContainer = root.Q("BuildPackageContainer");
if (_buildPackageNames.Count > 0)
{
int defaultIndex = GetDefaultPackageIndex(AssetBundleBuilderSettingData.Setting.BuildPackage);
_buildPackageField = new PopupField<string>(_buildPackageNames, defaultIndex);
_buildPackageField.label = "Build Package";
_buildPackageField.style.width = 350;
_buildPackageField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildPackage = _buildPackageField.value;
});
buildPackageContainer.Add(_buildPackageField);
}
else
{
_buildPackageField = new PopupField<string>();
_buildPackageField.label = "Build Package";
_buildPackageField.style.width = 350;
buildPackageContainer.Add(_buildPackageField);
}
private void RefreshBuildPipelineView()
{
// 清空扩展区域
_container.Clear();
// 加密方法
var encryptionContainer = root.Q("EncryptionContainer");
if (_encryptionServicesClassNames.Count > 0)
{
int defaultIndex = GetDefaultEncryptionIndex(AssetBundleBuilderSettingData.Setting.EncyptionClassName);
_encryptionField = new PopupField<string>(_encryptionServicesClassNames, defaultIndex);
_encryptionField.label = "Encryption";
_encryptionField.style.width = 350;
_encryptionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.EncyptionClassName = _encryptionField.value;
});
encryptionContainer.Add(_encryptionField);
}
else
{
_encryptionField = new PopupField<string>();
_encryptionField.label = "Encryption";
_encryptionField.style.width = 350;
encryptionContainer.Add(_encryptionField);
}
_buildPipeline = AssetBundleBuilderSetting.GetPackageBuildPipeline(_buildPackage);
_packageMenu.text = _buildPackage;
_pipelineMenu.text = _buildPipeline;
// 压缩方式选项
_compressionField = root.Q<EnumField>("Compression");
_compressionField.Init(AssetBundleBuilderSettingData.Setting.CompressOption);
_compressionField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.CompressOption);
_compressionField.style.width = 350;
_compressionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.CompressOption = (ECompressOption)_compressionField.value;
});
if (_viewClassDic.TryGetValue(_buildPipeline, out Type value))
{
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
var viewer = Activator.CreateInstance(value) as BuildPipelineViewerBase;
viewer.InitView(_buildPackage, _buildPipeline, buildTarget);
viewer.CreateView(_container);
}
else
{
Debug.LogError($"Not found build pipeline : {_buildPipeline}");
}
}
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
}
// 输出文件名称样式
_outputNameStyleField = root.Q<EnumField>("OutputNameStyle");
_outputNameStyleField.Init(AssetBundleBuilderSettingData.Setting.OutputNameStyle);
_outputNameStyleField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.OutputNameStyle);
_outputNameStyleField.style.width = 350;
_outputNameStyleField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.OutputNameStyle = (EOutputNameStyle)_outputNameStyleField.value;
});
private void PackageMenuAction(DropdownMenuAction action)
{
var packageName = (string)action.userData;
if (_buildPackage != packageName)
{
_buildPackage = packageName;
RefreshBuildPipelineView();
}
}
private DropdownMenuAction.Status PackageMenuFun(DropdownMenuAction action)
{
var packageName = (string)action.userData;
if (_buildPackage == packageName)
return DropdownMenuAction.Status.Checked;
else
return DropdownMenuAction.Status.Normal;
}
// 首包文件拷贝选项
_copyBuildinFileOptionField = root.Q<EnumField>("CopyBuildinFileOption");
_copyBuildinFileOptionField.Init(AssetBundleBuilderSettingData.Setting.CopyBuildinFileOption);
_copyBuildinFileOptionField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.CopyBuildinFileOption);
_copyBuildinFileOptionField.style.width = 350;
_copyBuildinFileOptionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.CopyBuildinFileOption = (ECopyBuildinFileOption)_copyBuildinFileOptionField.value;
RefreshWindow();
});
// 首包文件的资源标签
_copyBuildinFileTagsField = root.Q<TextField>("CopyBuildinFileTags");
_copyBuildinFileTagsField.SetValueWithoutNotify(AssetBundleBuilderSettingData.Setting.CopyBuildinFileTags);
_copyBuildinFileTagsField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.CopyBuildinFileTags = _copyBuildinFileTagsField.value;
});
// 构建按钮
var buildButton = root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked; ;
RefreshWindow();
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
public void OnDestroy()
{
if (AssetBundleBuilderSettingData.IsDirty)
AssetBundleBuilderSettingData.SaveFile();
}
public void Update()
{
if (_saveButton != null)
{
if (AssetBundleBuilderSettingData.IsDirty)
{
if (_saveButton.enabledSelf == false)
_saveButton.SetEnabled(true);
}
else
{
if (_saveButton.enabledSelf)
_saveButton.SetEnabled(false);
}
}
}
private void RefreshWindow()
{
var buildPipeline = AssetBundleBuilderSettingData.Setting.BuildPipeline;
var buildMode = AssetBundleBuilderSettingData.Setting.BuildMode;
var copyOption = AssetBundleBuilderSettingData.Setting.CopyBuildinFileOption;
bool enableElement = buildMode == EBuildMode.ForceRebuild;
bool tagsFiledVisible = copyOption == ECopyBuildinFileOption.ClearAndCopyByTags || copyOption == ECopyBuildinFileOption.OnlyCopyByTags;
if (buildPipeline == EBuildPipeline.BuiltinBuildPipeline)
{
_compressionField.SetEnabled(enableElement);
_outputNameStyleField.SetEnabled(enableElement);
_copyBuildinFileOptionField.SetEnabled(enableElement);
_copyBuildinFileTagsField.SetEnabled(enableElement);
}
else
{
_compressionField.SetEnabled(true);
_outputNameStyleField.SetEnabled(true);
_copyBuildinFileOptionField.SetEnabled(true);
_copyBuildinFileTagsField.SetEnabled(true);
}
_copyBuildinFileTagsField.visible = tagsFiledVisible;
}
private void SaveBtn_clicked()
{
AssetBundleBuilderSettingData.SaveFile();
}
private void BuildButton_clicked()
{
var buildMode = AssetBundleBuilderSettingData.Setting.BuildMode;
if (EditorUtility.DisplayDialog("提示", $"通过构建模式【{buildMode}】来构建!", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建
/// </summary>
private void ExecuteBuild()
{
BuildParameters buildParameters = new BuildParameters();
buildParameters.StreamingAssetsRoot = AssetBundleBuilderHelper.GetDefaultStreamingAssetsRoot();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildTarget = _buildTarget;
buildParameters.BuildPipeline = AssetBundleBuilderSettingData.Setting.BuildPipeline;
buildParameters.BuildMode = AssetBundleBuilderSettingData.Setting.BuildMode;
buildParameters.PackageName = AssetBundleBuilderSettingData.Setting.BuildPackage;
buildParameters.PackageVersion = _buildVersionField.value;
buildParameters.VerifyBuildingResult = true;
buildParameters.SharedPackRule = new ZeroRedundancySharedPackRule();
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.CompressOption = AssetBundleBuilderSettingData.Setting.CompressOption;
buildParameters.OutputNameStyle = AssetBundleBuilderSettingData.Setting.OutputNameStyle;
buildParameters.CopyBuildinFileOption = AssetBundleBuilderSettingData.Setting.CopyBuildinFileOption;
buildParameters.CopyBuildinFileTags = AssetBundleBuilderSettingData.Setting.CopyBuildinFileTags;
if (AssetBundleBuilderSettingData.Setting.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
{
buildParameters.SBPParameters = new BuildParameters.SBPBuildParameters();
buildParameters.SBPParameters.WriteLinkXML = true;
}
var builder = new AssetBundleBuilder();
var buildResult = builder.Run(buildParameters);
if (buildResult.Success)
{
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
// 构建版本相关
private string GetBuildPackageVersion()
{
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
}
// 构建包裹相关
private int GetDefaultPackageIndex(string packageName)
{
for (int index = 0; index < _buildPackageNames.Count; index++)
{
if (_buildPackageNames[index] == packageName)
{
return index;
}
}
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildPackage = _buildPackageNames[0];
return 0;
}
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
}
// 加密类相关
private int GetDefaultEncryptionIndex(string className)
{
for (int index = 0; index < _encryptionServicesClassNames.Count; index++)
{
if (_encryptionServicesClassNames[index] == className)
{
return index;
}
}
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.EncyptionClassName = _encryptionServicesClassNames[0];
return 0;
}
private List<Type> GetEncryptionServicesClassTypes()
{
return EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
}
private IEncryptionServices CreateEncryptionServicesInstance()
{
if (_encryptionField.index < 0)
return null;
var classType = _encryptionServicesClassTypes[_encryptionField.index];
return (IEncryptionServices)Activator.CreateInstance(classType);
}
}
private void PipelineMenuAction(DropdownMenuAction action)
{
if (_buildPipeline != action.name)
{
_buildPipeline = action.name;
AssetBundleBuilderSetting.SetPackageBuildPipeline(_buildPackage, _buildPipeline);
RefreshBuildPipelineView();
}
}
private DropdownMenuAction.Status PipelineMenuFun(DropdownMenuAction action)
{
if (_buildPipeline == action.name)
return DropdownMenuAction.Status.Checked;
else
return DropdownMenuAction.Status.Normal;
}
}
}
#endif

View File

@@ -1,18 +1,4 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;">
<ui:Button text="Save" display-tooltip-when-elided="true" name="SaveButton" style="background-color: rgb(56, 147, 58);" />
</uie:Toolbar>
<ui:VisualElement name="BuildContainer">
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
<uie:EnumField label="Build Pipeline" name="BuildPipeline" />
<uie:EnumField label="Build Mode" name="BuildMode" />
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" style="width: 350px;" />
<ui:VisualElement name="BuildPackageContainer" style="height: 24px;" />
<ui:VisualElement name="EncryptionContainer" style="height: 24px;" />
<uie:EnumField label="Compression" value="Center" name="Compression" />
<uie:EnumField label="Output Name Style" value="Center" name="OutputNameStyle" />
<uie:EnumField label="Copy Buildin File Option" value="Center" name="CopyBuildinFileOption" />
<ui:TextField picking-mode="Ignore" label="Copy Buildin File Tags" name="CopyBuildinFileTags" />
<ui:Button text="构建" display-tooltip-when-elided="true" name="Build" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
</ui:VisualElement>
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row;" />
<ui:VisualElement name="Container" />
</ui:UXML>

View File

@@ -3,35 +3,49 @@ using UnityEngine;
namespace YooAsset.Editor
{
public static class AssetBundleSimulateBuilder
{
/// <summary>
/// 模拟构建
/// </summary>
public static string SimulateBuild(string packageName)
{
Debug.Log($"Begin to create simulate package : {packageName}");
BuildParameters buildParameters = new BuildParameters();
buildParameters.StreamingAssetsRoot = AssetBundleBuilderHelper.GetDefaultStreamingAssetsRoot();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.BuildMode = EBuildMode.SimulateBuild;
buildParameters.PackageName = packageName;
buildParameters.PackageVersion = "Simulate";
buildParameters.EnableLog = false;
public static class AssetBundleSimulateBuilder
{
/// <summary>
/// 模拟构建
/// </summary>
public static PackageInvokeBuildResult SimulateBuild(PackageInvokeBuildParam buildParam)
{
string packageName = buildParam.PackageName;
string buildPipelineName = buildParam.BuildPipelineName;
AssetBundleBuilder builder = new AssetBundleBuilder();
var buildResult = builder.Run(buildParameters);
if (buildResult.Success)
{
string manifestFileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
return manifestFilePath;
}
else
{
return null;
}
}
}
if (buildPipelineName == "EditorSimulateBuildPipeline")
{
var buildParameters = new EditorSimulateBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = EBuildPipeline.EditorSimulateBuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.VirtualBundle;
buildParameters.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
buildParameters.PackageName = packageName;
buildParameters.PackageVersion = "Simulate";
buildParameters.FileNameStyle = EFileNameStyle.HashName;
buildParameters.BuildinFileCopyOption = EBuildinFileCopyOption.None;
buildParameters.BuildinFileCopyParams = string.Empty;
buildParameters.UseAssetDependencyDB = true;
var pipeline = new EditorSimulateBuildPipeline();
BuildResult buildResult = pipeline.Run(buildParameters, false);
if (buildResult.Success)
{
var reulst = new PackageInvokeBuildResult();
reulst.PackageRootDirectory = buildResult.OutputPackageDirectory;
return reulst;
}
else
{
Debug.LogError(buildResult.ErrorInfo);
throw new System.Exception($"{nameof(EditorSimulateBuildPipeline)} build failed !");
}
}
else
{
throw new System.NotImplementedException(buildPipelineName);
}
}
}
}

View File

@@ -5,209 +5,129 @@ using System.Linq;
namespace YooAsset.Editor
{
public class BuildAssetInfo
{
private bool _isAddAssetTags = false;
private readonly HashSet<string> _referenceBundleNames = new HashSet<string>();
public class BuildAssetInfo
{
private bool _isAddAssetTags = false;
private readonly HashSet<string> _referenceBundleNames = new HashSet<string>();
/// <summary>
/// 收集器类型
/// </summary>
public ECollectorType CollectorType { private set; get; }
/// <summary>
/// 收集器类型
/// </summary>
public ECollectorType CollectorType { private set; get; }
/// <summary>
/// 资源包完整名称
/// </summary>
public string BundleName { private set; get; }
/// <summary>
/// 资源包完整名称
/// </summary>
public string BundleName { private set; get; }
/// <summary>
/// 可寻址地址
/// </summary>
public string Address { private set; get; }
/// <summary>
/// 可寻址地址
/// </summary>
public string Address { private set; get; }
/// <summary>
/// 资源路径
/// </summary>
public string AssetPath { private set; get; }
/// <summary>
/// 资源信息
/// </summary>
public AssetInfo AssetInfo { private set; get; }
/// <summary>
/// 资源GUID
/// </summary>
public string AssetGUID { private set; get; }
/// <summary>
/// 资源的分类标签
/// </summary>
public readonly List<string> AssetTags = new List<string>();
/// <summary>
/// 是否为原生资源
/// </summary>
public bool IsRawAsset { private set; get; }
/// <summary>
/// 是否为着色器资源
/// </summary>
public bool IsShaderAsset { private set; get; }
/// <summary>
/// 资源的分类标签
/// </summary>
public readonly List<string> AssetTags = new List<string>();
/// <summary>
/// 资源包的分类标签
/// </summary>
public readonly List<string> BundleTags = new List<string>();
/// <summary>
/// 依赖的所有资源
/// 注意:包括零依赖资源和冗余资源(资源包名无效)
/// </summary>
public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }
/// <summary>
/// 依赖的所有资源
/// 注意:包括零依赖资源和冗余资源(资源包名无效)
/// </summary>
public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }
public BuildAssetInfo(ECollectorType collectorType, string bundleName, string address, string assetPath, bool isRawAsset)
{
CollectorType = collectorType;
BundleName = bundleName;
Address = address;
AssetPath = assetPath;
IsRawAsset = isRawAsset;
AssetGUID = UnityEditor.AssetDatabase.AssetPathToGUID(assetPath);
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader) || assetType == typeof(UnityEngine.ShaderVariantCollection))
IsShaderAsset = true;
else
IsShaderAsset = false;
}
public BuildAssetInfo(string assetPath)
{
CollectorType = ECollectorType.None;
Address = string.Empty;
AssetPath = assetPath;
IsRawAsset = false;
AssetGUID = UnityEditor.AssetDatabase.AssetPathToGUID(assetPath);
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader) || assetType == typeof(UnityEngine.ShaderVariantCollection))
IsShaderAsset = true;
else
IsShaderAsset = false;
}
public BuildAssetInfo(ECollectorType collectorType, string bundleName, string address, AssetInfo assetInfo)
{
CollectorType = collectorType;
BundleName = bundleName;
Address = address;
AssetInfo = assetInfo;
}
public BuildAssetInfo(AssetInfo assetInfo)
{
CollectorType = ECollectorType.None;
BundleName = string.Empty;
Address = string.Empty;
AssetInfo = assetInfo;
}
/// <summary>
/// 设置所有依赖的资源
/// </summary>
public void SetAllDependAssetInfos(List<BuildAssetInfo> dependAssetInfos)
{
if (AllDependAssetInfos != null)
throw new System.Exception("Should never get here !");
/// <summary>
/// 设置所有依赖的资源
/// </summary>
public void SetDependAssetInfos(List<BuildAssetInfo> dependAssetInfos)
{
if (AllDependAssetInfos != null)
throw new System.Exception("Should never get here !");
AllDependAssetInfos = dependAssetInfos;
}
AllDependAssetInfos = dependAssetInfos;
}
/// <summary>
/// 添加资源的分类标签
/// 说明:原始定义的资源分类标签
/// </summary>
public void AddAssetTags(List<string> tags)
{
if (_isAddAssetTags)
throw new Exception("Should never get here !");
_isAddAssetTags = true;
/// <summary>
/// 设置资源包名称
/// </summary>
public void SetBundleName(string bundleName)
{
if (HasBundleName())
throw new System.Exception("Should never get here !");
foreach (var tag in tags)
{
if (AssetTags.Contains(tag) == false)
{
AssetTags.Add(tag);
}
}
}
BundleName = bundleName;
}
/// <summary>
/// 添加资源的分类标签
/// 说明:传染算法统计到的分类标签
/// </summary>
public void AddBundleTags(List<string> tags)
{
foreach (var tag in tags)
{
if (BundleTags.Contains(tag) == false)
{
BundleTags.Add(tag);
}
}
}
/// <summary>
/// 添加资源的分类标签
/// 说明:原始定义的资源分类标签
/// </summary>
public void AddAssetTags(List<string> tags)
{
if (_isAddAssetTags)
throw new Exception("Should never get here !");
_isAddAssetTags = true;
/// <summary>
/// 资源包名是否存在
/// </summary>
public bool HasBundleName()
{
if (string.IsNullOrEmpty(BundleName))
return false;
else
return true;
}
foreach (var tag in tags)
{
if (AssetTags.Contains(tag) == false)
{
AssetTags.Add(tag);
}
}
}
/// <summary>
/// 添加关联的资源包名称
/// </summary>
public void AddReferenceBundleName(string bundleName)
{
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
/// <summary>
/// 添加关联的资源包名称
/// </summary>
public void AddReferenceBundleName(string bundleName)
{
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
if (_referenceBundleNames.Contains(bundleName) == false)
_referenceBundleNames.Add(bundleName);
}
if (_referenceBundleNames.Contains(bundleName) == false)
_referenceBundleNames.Add(bundleName);
}
/// <summary>
/// 计算共享资源包的完整包名
/// </summary>
public void CalculateShareBundleName(ISharedPackRule sharedPackRule, bool uniqueBundleName, string packageName, string shadersBundleName)
{
if (CollectorType != ECollectorType.None)
return;
/// <summary>
/// 资源包名是否存在
/// </summary>
public bool HasBundleName()
{
if (string.IsNullOrEmpty(BundleName))
return false;
else
return true;
}
if (IsRawAsset)
throw new Exception("Should never get here !");
if (IsShaderAsset)
{
BundleName = shadersBundleName;
}
else
{
if (_referenceBundleNames.Count > 1)
{
PackRuleResult packRuleResult = sharedPackRule.GetPackRuleResult(AssetPath);
BundleName = packRuleResult.GetShareBundleName(packageName, uniqueBundleName);
}
else
{
// 注意被引用次数小于1的资源不需要设置资源包名称
BundleName = string.Empty;
}
}
}
/// <summary>
/// 判断是否为冗余资源
/// </summary>
public bool IsRedundancyAsset()
{
if (HasBundleName())
return false;
return _referenceBundleNames.Count > 1;
}
/// <summary>
/// 获取关联资源包的数量
/// </summary>
public int GetReferenceBundleCount()
{
return _referenceBundleNames.Count;
}
}
/// <summary>
/// 获取关联资源包的数量
/// </summary>
public int GetReferenceBundleCount()
{
return _referenceBundleNames.Count;
}
}
}

View File

@@ -6,220 +6,206 @@ using UnityEditor;
namespace YooAsset.Editor
{
public class BuildBundleInfo
{
#region
/// <summary>
/// Unity引擎生成的哈希值构建内容的哈希值
/// </summary>
public string PackageUnityHash { set; get; }
public class BuildBundleInfo
{
#region
/// <summary>
/// Unity引擎生成的哈希值构建内容的哈希值
/// </summary>
public string PackageUnityHash { set; get; }
/// <summary>
/// Unity引擎生成的CRC
/// </summary>
public uint PackageUnityCRC { set; get; }
/// <summary>
/// Unity引擎生成的CRC
/// </summary>
public uint PackageUnityCRC { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public string PackageFileHash { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public string PackageFileHash { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public string PackageFileCRC { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public uint PackageFileCRC { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public long PackageFileSize { set; get; }
/// <summary>
/// 文件哈希值
/// </summary>
public long PackageFileSize { set; get; }
/// <summary>
/// 构建输出的文件路径
/// </summary>
public string BuildOutputFilePath { set; get; }
/// <summary>
/// 构建输出的文件路径
/// </summary>
public string BuildOutputFilePath { set; get; }
/// <summary>
/// 补丁包的源文件路径
/// </summary>
public string PackageSourceFilePath { set; get; }
/// <summary>
/// 补丁包的源文件路径
/// </summary>
public string PackageSourceFilePath { set; get; }
/// <summary>
/// 补丁包的目标文件路径
/// </summary>
public string PackageDestFilePath { set; get; }
/// <summary>
/// 补丁包的目标文件路径
/// </summary>
public string PackageDestFilePath { set; get; }
/// <summary>
/// 加密生成文件的路径
/// 注意:如果未加密该路径为空
/// </summary>
public string EncryptedFilePath { set; get; }
#endregion
/// <summary>
/// 加密生成文件的路径
/// 注意:如果未加密该路径为空
/// </summary>
public string EncryptedFilePath { set; get; }
#endregion
private readonly Dictionary<string, BuildAssetInfo> _packAssetDic = new Dictionary<string, BuildAssetInfo>(100);
/// <summary>
/// 参与构建的资源列表
/// 注意:不包含零依赖资源和冗余资源
/// </summary>
public readonly List<BuildAssetInfo> AllPackAssets = new List<BuildAssetInfo>(100);
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName { private set; get; }
/// <summary>
/// 加密文件
/// </summary>
public bool Encrypted { set; get; }
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName { private set; get; }
public BuildBundleInfo(string bundleName)
{
BundleName = bundleName;
}
/// <summary>
/// 参与构建的资源列表
/// 注意:不包含零依赖资源和冗余资源
/// </summary>
public readonly List<BuildAssetInfo> AllMainAssets = new List<BuildAssetInfo>();
/// <summary>
/// 添加一个打包资源
/// </summary>
public void PackAsset(BuildAssetInfo buildAsset)
{
string assetPath = buildAsset.AssetInfo.AssetPath;
if (_packAssetDic.ContainsKey(assetPath))
throw new System.Exception($"Should never get here ! Asset is existed : {assetPath}");
/// <summary>
/// Bundle文件的加载方法
/// </summary>
public EBundleLoadMethod LoadMethod { set; get; }
_packAssetDic.Add(assetPath, buildAsset);
AllPackAssets.Add(buildAsset);
}
/// <summary>
/// 是否为原生文件
/// </summary>
public bool IsRawFile
{
get
{
foreach (var assetInfo in AllMainAssets)
{
if (assetInfo.IsRawAsset)
return true;
}
return false;
}
}
/// <summary>
/// 是否包含指定资源
/// </summary>
public bool IsContainsPackAsset(string assetPath)
{
return _packAssetDic.ContainsKey(assetPath);
}
/// <summary>
/// 是否为加密文件
/// </summary>
public bool IsEncryptedFile
{
get
{
if (string.IsNullOrEmpty(EncryptedFilePath))
return false;
else
return true;
}
}
/// <summary>
/// 获取构建的资源路径列表
/// </summary>
public string[] GetAllPackAssetPaths()
{
List<string> results = new List<string>(AllPackAssets.Count);
for (int i = 0; i < AllPackAssets.Count; i++)
{
var packAsset = AllPackAssets[i];
results.Add(packAsset.AssetInfo.AssetPath);
}
return results.ToArray();
}
/// <summary>
/// 获取构建的资源可寻址列表
/// </summary>
public string[] GetAllPackAssetAddress()
{
List<string> results = new List<string>(AllPackAssets.Count);
for (int i = 0; i < AllPackAssets.Count; i++)
{
var packAsset = AllPackAssets[i];
results.Add(packAsset.Address);
}
return results.ToArray();
}
public BuildBundleInfo(string bundleName)
{
BundleName = bundleName;
}
/// <summary>
/// 获取构建的主资源信息
/// </summary>
public BuildAssetInfo GetPackAssetInfo(string assetPath)
{
if (_packAssetDic.TryGetValue(assetPath, out BuildAssetInfo value))
{
return value;
}
else
{
throw new Exception($"Can not found pack asset info {assetPath} in bundle : {BundleName}");
}
}
/// <summary>
/// 添加一个打包资源
/// </summary>
public void PackAsset(BuildAssetInfo assetInfo)
{
if (IsContainsAsset(assetInfo.AssetPath))
throw new System.Exception($"Asset is existed : {assetInfo.AssetPath}");
/// <summary>
/// 获取资源包内部所有资产
/// </summary>
public List<AssetInfo> GetBundleContents()
{
Dictionary<string, AssetInfo> result = new Dictionary<string, AssetInfo>(AllPackAssets.Count);
foreach (var packAsset in AllPackAssets)
{
result.Add(packAsset.AssetInfo.AssetPath, packAsset.AssetInfo);
if (packAsset.AllDependAssetInfos != null)
{
foreach (var dependAssetInfo in packAsset.AllDependAssetInfos)
{
// 注意:依赖资源里只添加零依赖资源和冗余资源
if (dependAssetInfo.HasBundleName() == false)
{
string dependAssetPath = dependAssetInfo.AssetInfo.AssetPath;
if (result.ContainsKey(dependAssetPath) == false)
result.Add(dependAssetPath, dependAssetInfo.AssetInfo);
}
}
}
}
return result.Values.ToList();
}
AllMainAssets.Add(assetInfo);
}
/// <summary>
/// 创建AssetBundleBuild类
/// </summary>
public UnityEditor.AssetBundleBuild CreatePipelineBuild(bool replaceAssetPathWithAddress)
{
// 注意我们不再支持AssetBundle的变种机制
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = BundleName;
build.assetBundleVariant = string.Empty;
build.assetNames = GetAllPackAssetPaths();
if (replaceAssetPathWithAddress)
build.addressableNames = GetAllPackAssetAddress();
return build;
}
/// <summary>
/// 是否包含指定资源
/// </summary>
public bool IsContainsAsset(string assetPath)
{
foreach (var assetInfo in AllMainAssets)
{
if (assetInfo.AssetPath == assetPath)
{
return true;
}
}
return false;
}
/// <summary>
/// 获取所有写入补丁清单的资源
/// </summary>
public BuildAssetInfo[] GetAllManifestAssetInfos()
{
return AllPackAssets.Where(t => t.CollectorType == ECollectorType.MainAssetCollector).ToArray();
}
/// <summary>
/// 获取资源包的分类标签列表
/// </summary>
public string[] GetBundleTags()
{
List<string> result = new List<string>(AllMainAssets.Count);
foreach (var assetInfo in AllMainAssets)
{
foreach (var assetTag in assetInfo.BundleTags)
{
if (result.Contains(assetTag) == false)
result.Add(assetTag);
}
}
return result.ToArray();
}
/// <summary>
/// 获取构建的资源路径列表
/// </summary>
public string[] GetAllMainAssetPaths()
{
return AllMainAssets.Select(t => t.AssetPath).ToArray();
}
/// <summary>
/// 获取该资源包内的所有资源(包括零依赖资源和冗余资源)
/// </summary>
public List<string> GetAllBuiltinAssetPaths()
{
var packAssets = GetAllMainAssetPaths();
List<string> result = new List<string>(packAssets);
foreach (var assetInfo in AllMainAssets)
{
if (assetInfo.AllDependAssetInfos == null)
continue;
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
{
// 注意:依赖资源里只添加零依赖资源和冗余资源
if (dependAssetInfo.HasBundleName() == false)
{
if (result.Contains(dependAssetInfo.AssetPath) == false)
result.Add(dependAssetInfo.AssetPath);
}
}
}
return result;
}
/// <summary>
/// 创建AssetBundleBuild类
/// </summary>
public UnityEditor.AssetBundleBuild CreatePipelineBuild()
{
// 注意我们不在支持AssetBundle的变种机制
AssetBundleBuild build = new AssetBundleBuild();
build.assetBundleName = BundleName;
build.assetBundleVariant = string.Empty;
build.assetNames = GetAllMainAssetPaths();
return build;
}
/// <summary>
/// 获取所有写入补丁清单的资源
/// </summary>
public BuildAssetInfo[] GetAllManifestAssetInfos()
{
return AllMainAssets.Where(t => t.CollectorType == ECollectorType.MainAssetCollector).ToArray();
}
/// <summary>
/// 创建PackageBundle类
/// </summary>
internal PackageBundle CreatePackageBundle()
{
PackageBundle packageBundle = new PackageBundle();
packageBundle.BundleName = BundleName;
packageBundle.FileHash = PackageFileHash;
packageBundle.FileCRC = PackageFileCRC;
packageBundle.FileSize = PackageFileSize;
packageBundle.UnityCRC = PackageUnityCRC;
packageBundle.IsRawFile = IsRawFile;
packageBundle.LoadMethod = (byte)LoadMethod;
packageBundle.Tags = GetBundleTags();
return packageBundle;
}
}
/// <summary>
/// 创建PackageBundle类
/// </summary>
internal PackageBundle CreatePackageBundle()
{
PackageBundle packageBundle = new PackageBundle();
packageBundle.BundleName = BundleName;
packageBundle.UnityCRC = PackageUnityCRC;
packageBundle.FileHash = PackageFileHash;
packageBundle.FileCRC = PackageFileCRC;
packageBundle.FileSize = PackageFileSize;
packageBundle.Encrypted = Encrypted;
return packageBundle;
}
}
}

View File

@@ -6,103 +6,116 @@ using UnityEditor;
namespace YooAsset.Editor
{
public class BuildMapContext : IContextObject
{
private readonly Dictionary<string, BuildBundleInfo> _bundleInfoDic = new Dictionary<string, BuildBundleInfo>(10000);
public class BuildMapContext : IContextObject
{
/// <summary>
/// 资源包集合
/// </summary>
private readonly Dictionary<string, BuildBundleInfo> _bundleInfoDic = new Dictionary<string, BuildBundleInfo>(10000);
/// <summary>
/// 冗余的资源列表
/// </summary>
public readonly List<ReportRedundancyInfo> RedundancyInfos= new List<ReportRedundancyInfo>(1000);
/// <summary>
/// 参与构建的资源总数
/// 说明:包括主动收集的资源以及其依赖的所有资源
/// </summary>
public int AssetFileCount;
/// <summary>
/// 图集资源集合
/// </summary>
public readonly List<BuildAssetInfo> SpriteAtlasAssetList = new List<BuildAssetInfo>(10000);
/// <summary>
/// 收集命令
/// </summary>
public CollectCommand Command { set; get; }
/// <summary>
/// 未被依赖的资源列表
/// </summary>
public readonly List<ReportIndependAsset> IndependAssets = new List<ReportIndependAsset>(1000);
/// <summary>
/// 资源包信息列表
/// </summary>
public Dictionary<string, BuildBundleInfo>.ValueCollection Collection
{
get
{
return _bundleInfoDic.Values;
}
}
/// <summary>
/// 参与构建的资源总数
/// 说明:包括主动收集的资源以及其依赖的所有资源
/// </summary>
public int AssetFileCount;
/// <summary>
/// 资源收集命令
/// </summary>
public CollectCommand Command { set; get; }
/// <summary>
/// 资源包信息列表
/// </summary>
public Dictionary<string, BuildBundleInfo>.ValueCollection Collection
{
get
{
return _bundleInfoDic.Values;
}
}
/// <summary>
/// 添加一个打包资源
/// </summary>
public void PackAsset(BuildAssetInfo assetInfo)
{
string bundleName = assetInfo.BundleName;
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
/// <summary>
/// 添加一个打包资源
/// </summary>
public void PackAsset(BuildAssetInfo assetInfo)
{
string bundleName = assetInfo.BundleName;
if (string.IsNullOrEmpty(bundleName))
throw new Exception("Should never get here !");
if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo bundleInfo))
{
bundleInfo.PackAsset(assetInfo);
}
else
{
BuildBundleInfo newBundleInfo = new BuildBundleInfo(bundleName);
newBundleInfo.PackAsset(assetInfo);
_bundleInfoDic.Add(bundleName, newBundleInfo);
}
}
if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo bundleInfo))
{
bundleInfo.PackAsset(assetInfo);
}
else
{
BuildBundleInfo newBundleInfo = new BuildBundleInfo(bundleName);
newBundleInfo.PackAsset(assetInfo);
_bundleInfoDic.Add(bundleName, newBundleInfo);
}
/// <summary>
/// 是否包含资源包
/// </summary>
public bool IsContainsBundle(string bundleName)
{
return _bundleInfoDic.ContainsKey(bundleName);
}
// 统计所有的精灵图集
if (assetInfo.AssetInfo.IsSpriteAtlas())
{
SpriteAtlasAssetList.Add(assetInfo);
}
}
/// <summary>
/// 获取资源包信息如果没找到返回NULL
/// </summary>
public BuildBundleInfo GetBundleInfo(string bundleName)
{
if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo result))
{
return result;
}
throw new Exception($"Not found bundle : {bundleName}");
}
/// <summary>
/// 是否包含资源包
/// </summary>
public bool IsContainsBundle(string bundleName)
{
return _bundleInfoDic.ContainsKey(bundleName);
}
/// <summary>
/// 获取构建管线里需要的数据
/// </summary>
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds()
{
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
foreach (var bundleInfo in _bundleInfoDic.Values)
{
if (bundleInfo.IsRawFile == false)
builds.Add(bundleInfo.CreatePipelineBuild());
}
return builds.ToArray();
}
/// <summary>
/// 获取资源包信息如果没找到返回NULL
/// </summary>
public BuildBundleInfo GetBundleInfo(string bundleName)
{
if (_bundleInfoDic.TryGetValue(bundleName, out BuildBundleInfo result))
{
return result;
}
throw new Exception($"Should never get here ! Not found bundle : {bundleName}");
}
/// <summary>
/// 创建着色器信息类
/// </summary>
public void CreateShadersBundleInfo(string shadersBundleName)
{
if (IsContainsBundle(shadersBundleName) == false)
{
var shaderBundleInfo = new BuildBundleInfo(shadersBundleName);
_bundleInfoDic.Add(shadersBundleName, shaderBundleInfo);
}
}
}
/// <summary>
/// 获取构建管线里需要的数据
/// </summary>
public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(bool replaceAssetPathWithAddres)
{
List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);
foreach (var bundleInfo in _bundleInfoDic.Values)
{
builds.Add(bundleInfo.CreatePipelineBuild(replaceAssetPathWithAddres));
}
return builds.ToArray();
}
/// <summary>
/// 创建空的资源包
/// </summary>
public void CreateEmptyBundleInfo(string bundleName)
{
if (IsContainsBundle(bundleName) == false)
{
var bundleInfo = new BuildBundleInfo(bundleName);
_bundleInfoDic.Add(bundleName, bundleInfo);
}
}
}
}

View File

@@ -1,125 +1,222 @@
using System.Collections;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
/// <summary>
/// 构建参数
/// </summary>
public class BuildParameters
{
/// <summary>
/// SBP构建参数
/// </summary>
public class SBPBuildParameters
{
/// <summary>
/// 生成代码防裁剪配置
/// </summary>
public bool WriteLinkXML = true;
/// <summary>
/// 构建参数
/// </summary>
public abstract class BuildParameters
{
/// <summary>
/// 构建输出的根目录
/// </summary>
public string BuildOutputRoot;
/// <summary>
/// 缓存服务器地址
/// </summary>
public string CacheServerHost;
/// <summary>
/// 内置文件的根目录
/// </summary>
public string BuildinFileRoot;
/// <summary>
/// 缓存服务器端口
/// </summary>
public int CacheServerPort;
}
/// <summary>
/// 构建管线名称
/// </summary>
public string BuildPipeline;
/// <summary>
/// 可编程构建管线的参数
/// </summary>
public SBPBuildParameters SBPParameters;
/// <summary>
/// 构建资源包类型
/// </summary>
public int BuildBundleType;
/// <summary>
/// 构建的平台
/// </summary>
public BuildTarget BuildTarget;
/// <summary>
/// 构建的包裹名称
/// </summary>
public string PackageName;
/// <summary>
/// 构建的包裹版本
/// </summary>
public string PackageVersion;
/// <summary>
/// 构建的包裹备注
/// </summary>
public string PackageNote;
/// <summary>
/// 清空构建缓存文件
/// </summary>
public bool ClearBuildCacheFiles = false;
/// <summary>
/// 使用资源依赖缓存数据库
/// 说明:开启此项可以极大提高资源收集速度!
/// </summary>
public bool UseAssetDependencyDB = false;
/// <summary>
/// 启用共享资源打包
/// </summary>
public bool EnableSharePackRule = false;
/// <summary>
/// 对单独引用的共享资源进行独立打包
/// 说明:关闭该选项单独引用的共享资源将会构建到引用它的资源包内!
/// </summary>
public bool SingleReferencedPackAlone = true;
/// <summary>
/// 验证构建结果
/// </summary>
public bool VerifyBuildingResult = false;
/// <summary>
/// 资源包名称样式
/// </summary>
public EFileNameStyle FileNameStyle = EFileNameStyle.HashName;
/// <summary>
/// 内置文件的拷贝选项
/// </summary>
public EBuildinFileCopyOption BuildinFileCopyOption = EBuildinFileCopyOption.None;
/// <summary>
/// 内置文件的拷贝参数
/// </summary>
public string BuildinFileCopyParams;
/// <summary>
/// 资源包加密服务类
/// </summary>
public IEncryptionServices EncryptionServices;
/// <summary>
/// 资源清单加密服务类
/// </summary>
public IManifestProcessServices ManifestProcessServices;
/// <summary>
/// 资源清单解密服务类
/// </summary>
public IManifestRestoreServices ManifestRestoreServices;
private string _pipelineOutputDirectory = string.Empty;
private string _packageOutputDirectory = string.Empty;
private string _packageRootDirectory = string.Empty;
private string _buildinRootDirectory = string.Empty;
/// <summary>
/// 检测构建参数是否合法
/// </summary>
public virtual void CheckBuildParameters()
{
// 检测当前是否正在构建资源包
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.ThePipelineIsBuiding, "The pipeline is buiding, please try again after finish !");
throw new Exception(message);
}
// 检测构建参数合法性
if (BuildTarget == BuildTarget.NoTarget)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.NoBuildTarget, "Please select the build target platform !");
throw new Exception(message);
}
if (string.IsNullOrEmpty(BuildOutputRoot))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildOutputRootIsNullOrEmpty, "Build output root is null or empty !");
throw new Exception(message);
}
if (string.IsNullOrEmpty(BuildinFileRoot))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildinFileRootIsNullOrEmpty, "Buildin file root is null or empty !");
throw new Exception(message);
}
if (string.IsNullOrEmpty(BuildPipeline))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildPipelineIsNullOrEmpty, "Build pipeline is null or empty !");
throw new Exception(message);
}
if (BuildBundleType == (int)EBuildBundleType.Unknown)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.BuildBundleTypeIsUnknown, $"Build bundle type is unknown {BuildBundleType} !");
throw new Exception(message);
}
if (string.IsNullOrEmpty(PackageName))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.PackageNameIsNullOrEmpty, "Package name is null or empty !");
throw new Exception(message);
}
if (string.IsNullOrEmpty(PackageVersion))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.PackageVersionIsNullOrEmpty, "Package version is null or empty !");
throw new Exception(message);
}
// 设置默认备注信息
if (string.IsNullOrEmpty(PackageNote))
{
PackageNote = DateTime.Now.ToString();
}
}
/// <summary>
/// 内置资源的根目录
/// </summary>
public string StreamingAssetsRoot;
/// <summary>
/// 获取构建管线的输出目录
/// </summary>
/// <returns></returns>
public virtual string GetPipelineOutputDirectory()
{
if (string.IsNullOrEmpty(_pipelineOutputDirectory))
{
_pipelineOutputDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{YooAssetSettings.OutputFolderName}";
}
return _pipelineOutputDirectory;
}
/// <summary>
/// 构建输出的根目录
/// </summary>
public string BuildOutputRoot;
/// <summary>
/// 获取本次构建的补丁输出目录
/// </summary>
public virtual string GetPackageOutputDirectory()
{
if (string.IsNullOrEmpty(_packageOutputDirectory))
{
_packageOutputDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}/{PackageVersion}";
}
return _packageOutputDirectory;
}
/// <summary>
/// 构建的平台
/// </summary>
public BuildTarget BuildTarget;
/// <summary>
/// 获取本次构建的补丁根目录
/// </summary>
public virtual string GetPackageRootDirectory()
{
if (string.IsNullOrEmpty(_packageRootDirectory))
{
_packageRootDirectory = $"{BuildOutputRoot}/{BuildTarget}/{PackageName}";
}
return _packageRootDirectory;
}
/// <summary>
/// 构建管线
/// </summary>
public EBuildPipeline BuildPipeline;
/// <summary>
/// 构建模式
/// </summary>
public EBuildMode BuildMode;
/// <summary>
/// 构建的包裹名称
/// </summary>
public string PackageName;
/// <summary>
/// 构建的包裹版本
/// </summary>
public string PackageVersion;
/// <summary>
/// 是否显示普通日志
/// </summary>
public bool EnableLog = true;
/// <summary>
/// 验证构建结果
/// </summary>
public bool VerifyBuildingResult = false;
/// <summary>
/// 共享资源的打包规则
/// </summary>
public ISharedPackRule SharedPackRule = null;
/// <summary>
/// 资源的加密接口
/// </summary>
public IEncryptionServices EncryptionServices = null;
/// <summary>
/// 补丁文件名称的样式
/// </summary>
public EOutputNameStyle OutputNameStyle = EOutputNameStyle.HashName;
/// <summary>
/// 拷贝内置资源选项
/// </summary>
public ECopyBuildinFileOption CopyBuildinFileOption = ECopyBuildinFileOption.None;
/// <summary>
/// 拷贝内置资源的标签
/// </summary>
public string CopyBuildinFileTags = string.Empty;
/// <summary>
/// 压缩选项
/// </summary>
public ECompressOption CompressOption = ECompressOption.Uncompressed;
/// <summary>
/// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
/// </summary>
public bool DisableWriteTypeTree = false;
/// <summary>
/// 忽略类型树变化
/// </summary>
public bool IgnoreTypeTreeChanges = true;
}
/// <summary>
/// 获取内置资源的根目录
/// </summary>
public virtual string GetBuildinRootDirectory()
{
if (string.IsNullOrEmpty(_buildinRootDirectory))
{
_buildinRootDirectory = $"{BuildinFileRoot}/{PackageName}";
}
return _buildinRootDirectory;
}
}
}

View File

@@ -1,145 +1,63 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
namespace YooAsset.Editor
{
public class BuildParametersContext : IContextObject
{
private string _pipelineOutputDirectory = string.Empty;
private string _packageOutputDirectory = string.Empty;
private string _packageRootDirectory = string.Empty;
private string _streamingAssetsDirectory = string.Empty;
/// <summary>
/// 构建参数
/// </summary>
public BuildParameters Parameters { private set; get; }
public class BuildParametersContext : IContextObject
{
/// <summary>
/// 构建参数
/// </summary>
public BuildParameters Parameters { private set; get; }
public BuildParametersContext(BuildParameters parameters)
{
Parameters = parameters;
}
public BuildParametersContext(BuildParameters parameters)
{
Parameters = parameters;
}
/// <summary>
/// 获取构建管线的输出目录
/// </summary>
/// <returns></returns>
public string GetPipelineOutputDirectory()
{
if (string.IsNullOrEmpty(_pipelineOutputDirectory))
{
_pipelineOutputDirectory = $"{Parameters.BuildOutputRoot}/{Parameters.BuildTarget}/{Parameters.PackageName}/{YooAssetSettings.OutputFolderName}";
}
return _pipelineOutputDirectory;
}
/// <summary>
/// 检测构建参数是否合法
/// </summary>
public void CheckBuildParameters()
{
Parameters.CheckBuildParameters();
}
/// <summary>
/// 获取本次构建的补丁输出目录
/// </summary>
public string GetPackageOutputDirectory()
{
if (string.IsNullOrEmpty(_packageOutputDirectory))
{
_packageOutputDirectory = $"{Parameters.BuildOutputRoot}/{Parameters.BuildTarget}/{Parameters.PackageName}/{Parameters.PackageVersion}";
}
return _packageOutputDirectory;
}
/// <summary>
/// 获取构建管线的输出目录
/// </summary>
/// <returns></returns>
public string GetPipelineOutputDirectory()
{
return Parameters.GetPipelineOutputDirectory();
}
/// <summary>
/// 获取本次构建的补丁目录
/// </summary>
public string GetPackageRootDirectory()
{
if (string.IsNullOrEmpty(_packageRootDirectory))
{
_packageRootDirectory = $"{Parameters.BuildOutputRoot}/{Parameters.BuildTarget}/{Parameters.PackageName}";
}
return _packageRootDirectory;
}
/// <summary>
/// 获取本次构建的补丁输出目录
/// </summary>
public string GetPackageOutputDirectory()
{
return Parameters.GetPackageOutputDirectory();
}
/// <summary>
/// 获取内置资源的目录
/// </summary>
public string GetStreamingAssetsDirectory()
{
if (string.IsNullOrEmpty(_streamingAssetsDirectory))
{
_streamingAssetsDirectory = $"{Parameters.StreamingAssetsRoot}/{Parameters.PackageName}";
}
return _streamingAssetsDirectory;
}
/// <summary>
/// 获取本次构建的补丁根目录
/// </summary>
public string GetPackageRootDirectory()
{
return Parameters.GetPackageRootDirectory();
}
/// <summary>
/// 获取内置构建管线的构建选项
/// </summary>
public BuildAssetBundleOptions GetPipelineBuildOptions()
{
// For the new build system, unity always need BuildAssetBundleOptions.CollectDependencies and BuildAssetBundleOptions.DeterministicAssetBundle
// 除非设置ForceRebuildAssetBundle标记否则会进行增量打包
if (Parameters.BuildMode == EBuildMode.SimulateBuild)
throw new Exception("Should never get here !");
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
if (Parameters.BuildMode == EBuildMode.DryRunBuild)
{
opt |= BuildAssetBundleOptions.DryRunBuild;
return opt;
}
if (Parameters.CompressOption == ECompressOption.Uncompressed)
opt |= BuildAssetBundleOptions.UncompressedAssetBundle;
else if (Parameters.CompressOption == ECompressOption.LZ4)
opt |= BuildAssetBundleOptions.ChunkBasedCompression;
if (Parameters.BuildMode == EBuildMode.ForceRebuild)
opt |= BuildAssetBundleOptions.ForceRebuildAssetBundle; //Force rebuild the asset bundles
if (Parameters.DisableWriteTypeTree)
opt |= BuildAssetBundleOptions.DisableWriteTypeTree; //Do not include type information within the asset bundle (don't write type tree).
if (Parameters.IgnoreTypeTreeChanges)
opt |= BuildAssetBundleOptions.IgnoreTypeTreeChanges; //Ignore the type tree changes when doing the incremental build check.
opt |= BuildAssetBundleOptions.DisableLoadAssetByFileName; //Disables Asset Bundle LoadAsset by file name.
opt |= BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension; //Disables Asset Bundle LoadAsset by file name with extension.
return opt;
}
/// <summary>
/// 获取可编程构建管线的构建参数
/// </summary>
public UnityEditor.Build.Pipeline.BundleBuildParameters GetSBPBuildParameters()
{
if (Parameters.BuildMode == EBuildMode.SimulateBuild)
throw new Exception("Should never get here !");
var targetGroup = BuildPipeline.GetBuildTargetGroup(Parameters.BuildTarget);
var pipelineOutputDirectory = GetPipelineOutputDirectory();
var buildParams = new UnityEditor.Build.Pipeline.BundleBuildParameters(Parameters.BuildTarget, targetGroup, pipelineOutputDirectory);
if (Parameters.CompressOption == ECompressOption.Uncompressed)
buildParams.BundleCompression = UnityEngine.BuildCompression.Uncompressed;
else if (Parameters.CompressOption == ECompressOption.LZMA)
buildParams.BundleCompression = UnityEngine.BuildCompression.LZMA;
else if (Parameters.CompressOption == ECompressOption.LZ4)
buildParams.BundleCompression = UnityEngine.BuildCompression.LZ4;
else
throw new System.NotImplementedException(Parameters.CompressOption.ToString());
if (Parameters.DisableWriteTypeTree)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;
buildParams.UseCache = true;
buildParams.CacheServerHost = Parameters.SBPParameters.CacheServerHost;
buildParams.CacheServerPort = Parameters.SBPParameters.CacheServerPort;
buildParams.WriteLinkXML = Parameters.SBPParameters.WriteLinkXML;
return buildParams;
}
}
/// <summary>
/// 获取内置资源的根目录
/// </summary>
public string GetBuildinRootDirectory()
{
return Parameters.GetBuildinRootDirectory();
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d29a9623b2b346e439b7a7e37fafa781
guid: 431722e1bca52d448825f603789d7e4b
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskCopyBuildinFiles
{
/// <summary>
/// 拷贝首包资源文件
/// </summary>
internal void CopyBuildinFilesToStreaming(BuildParametersContext buildParametersContext, PackageManifest manifest)
{
EBuildinFileCopyOption copyOption = buildParametersContext.Parameters.BuildinFileCopyOption;
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
string buildPackageName = buildParametersContext.Parameters.PackageName;
string buildPackageVersion = buildParametersContext.Parameters.PackageVersion;
// 清空内置文件的目录
if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.ClearAndCopyByTags)
{
EditorTools.ClearFolder(buildinRootDirectory);
}
// 拷贝补丁清单文件
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildPackageName, buildPackageVersion);
string sourcePath = $"{packageOutputDirectory}/{fileName}";
string destPath = $"{buildinRootDirectory}/{fileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝补丁清单哈希文件
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildPackageName, buildPackageVersion);
string sourcePath = $"{packageOutputDirectory}/{fileName}";
string destPath = $"{buildinRootDirectory}/{fileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝补丁清单版本文件
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildPackageName);
string sourcePath = $"{packageOutputDirectory}/{fileName}";
string destPath = $"{buildinRootDirectory}/{fileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝文件列表(所有文件)
if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.OnlyCopyAll)
{
foreach (var packageBundle in manifest.BundleList)
{
string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
}
// 拷贝文件列表(带标签的文件)
if (copyOption == EBuildinFileCopyOption.ClearAndCopyByTags || copyOption == EBuildinFileCopyOption.OnlyCopyByTags)
{
string[] tags = buildParametersContext.Parameters.BuildinFileCopyParams.Split(';');
foreach (var packageBundle in manifest.BundleList)
{
if (packageBundle.HasTag(tags) == false)
continue;
string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
}
// 刷新目录
AssetDatabase.Refresh();
BuildLogger.Log($"Buildin files copy complete: {buildinRootDirectory}");
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskCreateCatalog
{
/// <summary>
/// 生成内置资源记录文件
/// </summary>
internal void CreateCatalogFile(BuildParametersContext buildParametersContext)
{
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
string buildPackageName = buildParametersContext.Parameters.PackageName;
var manifestServices = buildParametersContext.Parameters.ManifestRestoreServices;
CatalogTools.CreateCatalogFile(manifestServices, buildPackageName, buildinRootDirectory);
// 刷新目录
AssetDatabase.Refresh();
}
}
}

View File

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

View File

@@ -0,0 +1,409 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class ManifestContext : IContextObject
{
internal PackageManifest Manifest;
}
public abstract class TaskCreateManifest
{
private readonly Dictionary<string, int> _cachedBundleIndexIDs = new Dictionary<string, int>(10000);
private readonly Dictionary<int, HashSet<string>> _cacheBundleTags = new Dictionary<int, HashSet<string>>(10000);
/// <summary>
/// 创建补丁清单文件到输出目录
/// </summary>
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, bool replaceAssetPathWithAddress, BuildContext context)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters;
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
// 检测资源包哈希冲突
CheckBundleHashConflict(buildMapContext);
// 创建新补丁清单
PackageManifest manifest = new PackageManifest();
manifest.FileVersion = ManifestDefine.FileVersion;
manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
manifest.ReplaceAssetPathWithAddress = replaceAssetPathWithAddress;
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
manifest.BuildBundleType = buildParameters.BuildBundleType;
manifest.BuildPipeline = buildParameters.BuildPipeline;
manifest.PackageName = buildParameters.PackageName;
manifest.PackageVersion = buildParameters.PackageVersion;
manifest.PackageNote = buildParameters.PackageNote;
manifest.AssetList = CreatePackageAssetList(buildMapContext);
manifest.BundleList = CreatePackageBundleList(buildMapContext);
// 1. 处理资源清单的资源对象
ProcessPacakgeAsset(manifest);
// 2. 处理资源包的依赖列表
if (processBundleDepends)
ProcessBundleDepends(context, manifest);
// 3. 处理资源包的标签集合
if (processBundleTags)
ProcessBundleTags(manifest);
// 4. 处理内置资源包
if (processBundleDepends)
{
// 注意:初始化资源清单建立引用关系
manifest.Initialize();
ProcessBuiltinBundleDependency(context, manifest);
}
// 创建资源清单文本文件
{
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
ManifestTools.SerializeToJson(filePath, manifest);
BuildLogger.Log($"Create package manifest file: {filePath}");
}
// 创建资源清单二进制文件
string packageHash;
string packagePath;
{
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
packagePath = $"{packageOutputDirectory}/{fileName}";
ManifestTools.SerializeToBinary(packagePath, manifest, buildParameters.ManifestProcessServices);
packageHash = HashUtility.FileCRC32(packagePath);
BuildLogger.Log($"Create package manifest file: {packagePath}");
}
// 创建资源清单哈希文件
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
FileUtility.WriteAllText(filePath, packageHash);
BuildLogger.Log($"Create package manifest hash file: {filePath}");
}
// 创建资源清单版本文件
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
string filePath = $"{packageOutputDirectory}/{fileName}";
FileUtility.WriteAllText(filePath, buildParameters.PackageVersion);
BuildLogger.Log($"Create package manifest version file: {filePath}");
}
// 填充上下文
{
ManifestContext manifestContext = new ManifestContext();
byte[] bytesData = FileUtility.ReadAllBytes(packagePath);
manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData, buildParameters.ManifestRestoreServices);
context.SetContextObject(manifestContext);
}
}
/// <summary>
/// 检测资源包哈希冲突
/// </summary>
private void CheckBundleHashConflict(BuildMapContext buildMapContext)
{
// 说明:在特殊情况下,例如某些文件加密算法会导致加密后的文件哈希值冲突!
// 说明:二进制完全相同的原生文件也会冲突!
HashSet<string> guids = new HashSet<string>();
foreach (var bundleInfo in buildMapContext.Collection)
{
if (guids.Contains(bundleInfo.PackageFileHash))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.BundleHashConflict, $"Bundle hash conflict : {bundleInfo.BundleName}");
throw new Exception(message);
}
else
{
guids.Add(bundleInfo.PackageFileHash);
}
}
}
/// <summary>
/// 获取资源包的依赖集合
/// </summary>
protected abstract string[] GetBundleDepends(BuildContext context, string bundleName);
/// <summary>
/// 创建资源对象列表
/// </summary>
private List<PackageAsset> CreatePackageAssetList(BuildMapContext buildMapContext)
{
List<PackageAsset> result = new List<PackageAsset>(1000);
foreach (var bundleInfo in buildMapContext.Collection)
{
var assetInfos = bundleInfo.GetAllManifestAssetInfos();
foreach (var assetInfo in assetInfos)
{
PackageAsset packageAsset = new PackageAsset();
packageAsset.Address = buildMapContext.Command.EnableAddressable ? assetInfo.Address : string.Empty;
packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath;
packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty;
packageAsset.AssetTags = assetInfo.AssetTags.ToArray();
packageAsset.TempDataInEditor = assetInfo;
result.Add(packageAsset);
}
}
// 按照AssetPath排序
result.Sort((a, b) => a.AssetPath.CompareTo(b.AssetPath));
return result;
}
/// <summary>
/// 创建资源包列表
/// </summary>
private List<PackageBundle> CreatePackageBundleList(BuildMapContext buildMapContext)
{
List<PackageBundle> result = new List<PackageBundle>(1000);
foreach (var bundleInfo in buildMapContext.Collection)
{
var packageBundle = bundleInfo.CreatePackageBundle();
result.Add(packageBundle);
}
// 按照BundleName排序
result.Sort((a, b) => a.BundleName.CompareTo(b.BundleName));
return result;
}
/// <summary>
/// 处理资源清单的资源对象列表
/// </summary>
private void ProcessPacakgeAsset(PackageManifest manifest)
{
// 注意:优先缓存资源包索引
for (int index = 0; index < manifest.BundleList.Count; index++)
{
string bundleName = manifest.BundleList[index].BundleName;
_cachedBundleIndexIDs.Add(bundleName, index);
}
// 记录资源对象所属的资源包ID
foreach (var packageAsset in manifest.AssetList)
{
var assetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
packageAsset.BundleID = GetCachedBundleIndexID(assetInfo.BundleName);
}
// 记录资源对象依赖的资源包ID集合
// 注意:依赖关系非引擎构建结果里查询!
foreach (var packageAsset in manifest.AssetList)
{
var mainAssetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
packageAsset.DependBundleIDs = GetAssetDependBundleIDs(mainAssetInfo);
}
}
/// <summary>
/// 处理资源包的依赖集合
/// </summary>
private void ProcessBundleDepends(BuildContext context, PackageManifest manifest)
{
// 查询引擎生成的资源包依赖关系,然后记录到清单
foreach (var packageBundle in manifest.BundleList)
{
int mainBundleID = GetCachedBundleIndexID(packageBundle.BundleName);
string[] dependNames = GetBundleDepends(context, packageBundle.BundleName);
List<int> dependIDs = new List<int>(dependNames.Length);
foreach (var dependName in dependNames)
{
int dependBundleID = GetCachedBundleIndexID(dependName);
if (dependBundleID != mainBundleID)
dependIDs.Add(dependBundleID);
}
// 排序并填充数据
dependIDs.Sort();
packageBundle.DependBundleIDs = dependIDs.ToArray();
}
}
/// <summary>
/// 处理资源包的标签集合
/// </summary>
private void ProcessBundleTags(PackageManifest manifest)
{
foreach (var packageBundle in manifest.BundleList)
{
packageBundle.Tags = Array.Empty<string>();
}
// 将主资源的标签信息传染给其依赖的资源包集合
foreach (var packageAsset in manifest.AssetList)
{
var assetTags = packageAsset.AssetTags;
int bundleID = packageAsset.BundleID;
CacheBundleTags(bundleID, assetTags);
if (packageAsset.DependBundleIDs != null)
{
foreach (var dependBundleID in packageAsset.DependBundleIDs)
{
CacheBundleTags(dependBundleID, assetTags);
}
}
}
// 将缓存的资源标签赋值给资源包
for (int index = 0; index < manifest.BundleList.Count; index++)
{
var packageBundle = manifest.BundleList[index];
if (_cacheBundleTags.TryGetValue(index, out var value))
{
packageBundle.Tags = value.ToArray();
}
else
{
// 注意SBP构建管线会自动剔除一些冗余资源的引用关系导致游离资源包没有被任何主资源包引用。
string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundStrayBundle, $"Found stray bundle ! Bundle ID : {index} Bundle name : {packageBundle.BundleName}");
BuildLogger.Warning(warning);
}
}
}
private void CacheBundleTags(int bundleID, string[] assetTags)
{
if (_cacheBundleTags.ContainsKey(bundleID) == false)
_cacheBundleTags.Add(bundleID, new HashSet<string>());
foreach (var assetTag in assetTags)
{
if (_cacheBundleTags[bundleID].Contains(assetTag) == false)
_cacheBundleTags[bundleID].Add(assetTag);
}
}
/// <summary>
/// 获取缓存的资源包的索引ID
/// </summary>
private int GetCachedBundleIndexID(string bundleName)
{
if (_cachedBundleIndexIDs.TryGetValue(bundleName, out int value) == false)
{
throw new Exception($"Should never get here ! Not found bundle index ID : {bundleName}");
}
return value;
}
/// <summary>
/// 是否包含该资源包的索引ID
/// </summary>
private bool ContainsCachedBundleIndexID(string bundleName)
{
return _cachedBundleIndexIDs.ContainsKey(bundleName);
}
#region YOOASSET_LEGACY_DEPENDENCY
private void ProcessBuiltinBundleDependency(BuildContext context, PackageManifest manifest)
{
// 注意:如果是可编程构建管线,需要补充内置资源包
// 注意:该步骤依赖前面的操作!
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
if (buildResultContext != null)
{
ProcessBuiltinBundleReference(manifest, buildResultContext.BuiltinShadersBundleName);
ProcessBuiltinBundleReference(manifest, buildResultContext.MonoScriptsBundleName);
var buildParametersContext = context.TryGetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters;
if (buildParameters is ScriptableBuildParameters scriptableBuildParameters)
{
if (scriptableBuildParameters.TrackSpriteAtlasDependencies)
{
// 注意:检测是否开启图集模式
// 说明:需要记录主资源对象对图集的依赖关系!
if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
foreach (var spriteAtlasAsset in buildMapContext.SpriteAtlasAssetList)
{
string spriteAtlasBundleName = spriteAtlasAsset.BundleName;
ProcessBuiltinBundleReference(manifest, spriteAtlasBundleName);
}
}
}
}
}
}
private void ProcessBuiltinBundleReference(PackageManifest manifest, string builtinBundleName)
{
if (string.IsNullOrEmpty(builtinBundleName))
return;
// 查询内置资源包是否存在
if (ContainsCachedBundleIndexID(builtinBundleName) == false)
return;
// 获取内置资源包
int builtinBundleID = GetCachedBundleIndexID(builtinBundleName);
var builtinPackageBundle = manifest.BundleList[builtinBundleID];
// 更新依赖资源包ID集合
HashSet<int> cacheBundleIDs = new HashSet<int>(builtinPackageBundle.ReferenceBundleIDs);
HashSet<string> tempTags = new HashSet<string>();
foreach (var packageAsset in manifest.AssetList)
{
if (cacheBundleIDs.Contains(packageAsset.BundleID))
{
if (packageAsset.DependBundleIDs.Contains(builtinBundleID) == false)
{
var tempBundleIDs = new List<int>(packageAsset.DependBundleIDs);
tempBundleIDs.Add(builtinBundleID);
packageAsset.DependBundleIDs = tempBundleIDs.ToArray();
}
foreach (var tag in packageAsset.AssetTags)
{
if (tempTags.Contains(tag) == false)
tempTags.Add(tag);
}
}
}
// 更新内置资源包的标签集合
foreach (var tag in builtinPackageBundle.Tags)
{
if (tempTags.Contains(tag) == false)
tempTags.Add(tag);
}
builtinPackageBundle.Tags = tempTags.ToArray();
}
private int[] GetAssetDependBundleIDs(BuildAssetInfo mainAssetInfo)
{
HashSet<int> result = new HashSet<int>();
int mainBundleID = GetCachedBundleIndexID(mainAssetInfo.BundleName);
foreach (var dependAssetInfo in mainAssetInfo.AllDependAssetInfos)
{
if (dependAssetInfo.HasBundleName())
{
int bundleID = GetCachedBundleIndexID(dependAssetInfo.BundleName);
if (mainBundleID != bundleID)
{
if (result.Contains(bundleID) == false)
result.Add(bundleID);
}
}
}
// 排序并返回数据
List<int> listResult = new List<int>(result);
listResult.Sort();
return listResult.ToArray();
}
#endregion
}
}

View File

@@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskCreateReport
{
protected void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext, ManifestContext manifestContext)
{
var buildParameters = buildParametersContext.Parameters;
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
PackageManifest manifest = manifestContext.Manifest;
BuildReport buildReport = new BuildReport();
// 概述信息
{
buildReport.Summary.YooVersion = EditorTools.GetPackageManagerYooVersion();
buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion;
buildReport.Summary.BuildDate = DateTime.Now.ToString();
buildReport.Summary.BuildSeconds = BuildRunner.TotalSeconds;
buildReport.Summary.BuildTarget = buildParameters.BuildTarget;
buildReport.Summary.BuildPipeline = buildParameters.BuildPipeline;
buildReport.Summary.BuildBundleType = buildParameters.BuildBundleType;
buildReport.Summary.BuildPackageName = buildParameters.PackageName;
buildReport.Summary.BuildPackageVersion = buildParameters.PackageVersion;
buildReport.Summary.BuildPackageNote = buildParameters.PackageNote;
// 收集器配置
buildReport.Summary.UniqueBundleName = buildMapContext.Command.UniqueBundleName;
buildReport.Summary.EnableAddressable = buildMapContext.Command.EnableAddressable;
buildReport.Summary.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
buildReport.Summary.LocationToLower = buildMapContext.Command.LocationToLower;
buildReport.Summary.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders;
buildReport.Summary.IgnoreRuleName = buildMapContext.Command.IgnoreRule.GetType().FullName;
// 构建参数
buildReport.Summary.ClearBuildCacheFiles = buildParameters.ClearBuildCacheFiles;
buildReport.Summary.UseAssetDependencyDB = buildParameters.UseAssetDependencyDB;
buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;
buildReport.Summary.SingleReferencedPackAlone = buildParameters.SingleReferencedPackAlone;
buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
buildReport.Summary.EncryptionServicesClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName;
buildReport.Summary.ManifestProcessServicesClassName = buildParameters.ManifestProcessServices == null ? "null" : buildParameters.ManifestProcessServices.GetType().FullName;
buildReport.Summary.ManifestRestoreServicesClassName = buildParameters.ManifestRestoreServices == null ? "null" : buildParameters.ManifestRestoreServices.GetType().FullName;
if (buildParameters is BuiltinBuildParameters)
{
var builtinBuildParameters = buildParameters as BuiltinBuildParameters;
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
}
else if (buildParameters is ScriptableBuildParameters)
{
var scriptableBuildParameters = buildParameters as ScriptableBuildParameters;
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
buildReport.Summary.ReplaceAssetPathWithAddress = scriptableBuildParameters.ReplaceAssetPathWithAddress;
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;
buildReport.Summary.BuiltinShadersBundleName = scriptableBuildParameters.BuiltinShadersBundleName;
buildReport.Summary.MonoScriptsBundleName = scriptableBuildParameters.MonoScriptsBundleName;
}
// 构建结果
buildReport.Summary.AssetFileTotalCount = buildMapContext.AssetFileCount;
buildReport.Summary.MainAssetTotalCount = GetMainAssetCount(manifest);
buildReport.Summary.AllBundleTotalCount = GetAllBundleCount(manifest);
buildReport.Summary.AllBundleTotalSize = GetAllBundleSize(manifest);
buildReport.Summary.EncryptedBundleTotalCount = GetEncryptedBundleCount(manifest);
buildReport.Summary.EncryptedBundleTotalSize = GetEncryptedBundleSize(manifest);
}
// 资源对象列表
buildReport.AssetInfos = new List<ReportAssetInfo>(manifest.AssetList.Count);
foreach (var packageAsset in manifest.AssetList)
{
var mainBundle = manifest.BundleList[packageAsset.BundleID];
ReportAssetInfo reportAssetInfo = new ReportAssetInfo();
reportAssetInfo.Address = packageAsset.Address;
reportAssetInfo.AssetPath = packageAsset.AssetPath;
reportAssetInfo.AssetTags = packageAsset.AssetTags;
reportAssetInfo.AssetGUID = AssetDatabase.AssetPathToGUID(packageAsset.AssetPath);
reportAssetInfo.MainBundleName = mainBundle.BundleName;
reportAssetInfo.MainBundleSize = mainBundle.FileSize;
reportAssetInfo.DependAssets = GetAssetDependAssets(buildMapContext, mainBundle.BundleName, packageAsset.AssetPath);
reportAssetInfo.DependBundles = GetAssetDependBundles(manifest, packageAsset);
buildReport.AssetInfos.Add(reportAssetInfo);
}
// 资源包列表
buildReport.BundleInfos = new List<ReportBundleInfo>(manifest.BundleList.Count);
foreach (var packageBundle in manifest.BundleList)
{
ReportBundleInfo reportBundleInfo = new ReportBundleInfo();
reportBundleInfo.BundleName = packageBundle.BundleName;
reportBundleInfo.FileName = packageBundle.FileName;
reportBundleInfo.FileHash = packageBundle.FileHash;
reportBundleInfo.FileCRC = packageBundle.FileCRC;
reportBundleInfo.FileSize = packageBundle.FileSize;
reportBundleInfo.Encrypted = packageBundle.Encrypted;
reportBundleInfo.Tags = packageBundle.Tags;
reportBundleInfo.DependBundles = GetBundleDependBundles(manifest, packageBundle);
reportBundleInfo.ReferenceBundles = GetBundleReferenceBundles(manifest, packageBundle);
reportBundleInfo.BundleContents = GetBundleContents(buildMapContext, packageBundle.BundleName);
buildReport.BundleInfos.Add(reportBundleInfo);
}
// 其它资源列表
buildReport.IndependAssets = new List<ReportIndependAsset>(buildMapContext.IndependAssets);
// 序列化文件
string fileName = YooAssetSettingsData.GetBuildReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
BuildReport.Serialize(filePath, buildReport);
BuildLogger.Log($"Create build report file: {filePath}");
}
/// <summary>
/// 获取资源对象依赖的其它所有资源
/// </summary>
private List<AssetInfo> GetAssetDependAssets(BuildMapContext buildMapContext, string bundleName, string assetPath)
{
List<AssetInfo> result = new List<AssetInfo>();
var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
var assetInfo = bundleInfo.GetPackAssetInfo(assetPath);
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
{
result.Add(dependAssetInfo.AssetInfo);
}
result.Sort();
return result;
}
/// <summary>
/// 获取资源对象依赖的资源包集合
/// </summary>
private List<string> GetAssetDependBundles(PackageManifest manifest, PackageAsset packageAsset)
{
List<string> dependBundles = new List<string>(packageAsset.DependBundleIDs.Length);
foreach (int index in packageAsset.DependBundleIDs)
{
string dependBundleName = manifest.BundleList[index].BundleName;
dependBundles.Add(dependBundleName);
}
dependBundles.Sort();
return dependBundles;
}
/// <summary>
/// 获取资源包依赖的资源包集合
/// </summary>
private List<string> GetBundleDependBundles(PackageManifest manifest, PackageBundle packageBundle)
{
List<string> dependBundles = new List<string>(packageBundle.DependBundleIDs.Length);
foreach (int index in packageBundle.DependBundleIDs)
{
string dependBundleName = manifest.BundleList[index].BundleName;
dependBundles.Add(dependBundleName);
}
dependBundles.Sort();
return dependBundles;
}
/// <summary>
/// 获取引用该资源包的资源包集合
/// </summary>
private List<string> GetBundleReferenceBundles(PackageManifest manifest, PackageBundle packageBundle)
{
List<string> referenceBundles = new List<string>(packageBundle.ReferenceBundleIDs.Count);
foreach (int index in packageBundle.ReferenceBundleIDs)
{
string dependBundleName = manifest.BundleList[index].BundleName;
referenceBundles.Add(dependBundleName);
}
referenceBundles.Sort();
return referenceBundles;
}
/// <summary>
/// 获取资源包内部所有资产
/// </summary>
private List<AssetInfo> GetBundleContents(BuildMapContext buildMapContext, string bundleName)
{
var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
List<AssetInfo> result = bundleInfo.GetBundleContents();
result.Sort();
return result;
}
private int GetMainAssetCount(PackageManifest manifest)
{
return manifest.AssetList.Count;
}
private int GetAllBundleCount(PackageManifest manifest)
{
return manifest.BundleList.Count;
}
private long GetAllBundleSize(PackageManifest manifest)
{
long fileBytes = 0;
foreach (var packageBundle in manifest.BundleList)
{
fileBytes += packageBundle.FileSize;
}
return fileBytes;
}
private int GetEncryptedBundleCount(PackageManifest manifest)
{
int fileCount = 0;
foreach (var packageBundle in manifest.BundleList)
{
if (packageBundle.Encrypted)
fileCount++;
}
return fileCount;
}
private long GetEncryptedBundleSize(PackageManifest manifest)
{
long fileBytes = 0;
foreach (var packageBundle in manifest.BundleList)
{
if (packageBundle.Encrypted)
fileBytes += packageBundle.FileSize;
}
return fileBytes;
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Linq;
using System.IO;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
public class TaskEncryption
{
/// <summary>
/// 加密文件
/// </summary>
public void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
{
var encryptionServices = buildParametersContext.Parameters.EncryptionServices;
if (encryptionServices == null)
return;
if (encryptionServices.GetType() == typeof(EncryptionNone))
return;
int progressValue = 0;
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
foreach (var bundleInfo in buildMapContext.Collection)
{
EncryptFileInfo fileInfo = new EncryptFileInfo();
fileInfo.BundleName = bundleInfo.BundleName;
fileInfo.FileLoadPath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
var encryptResult = encryptionServices.Encrypt(fileInfo);
if (encryptResult.Encrypted)
{
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt";
FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedData);
bundleInfo.EncryptedFilePath = filePath;
bundleInfo.Encrypted = true;
BuildLogger.Log($"Bundle file encryption complete: {filePath}");
}
else
{
bundleInfo.Encrypted = false;
}
// 进度条
EditorTools.DisplayProgressBar("Encrypting bundle", ++progressValue, buildMapContext.Collection.Count);
}
EditorTools.ClearProgressBar();
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskGetBuildMap
{
/// <summary>
/// 生成资源构建上下文
/// </summary>
public BuildMapContext CreateBuildMap(bool simulateBuild, BuildParameters buildParameters)
{
BuildMapContext context = new BuildMapContext();
var packageName = buildParameters.PackageName;
Dictionary<string, BuildAssetInfo> allBuildAssetInfos = new Dictionary<string, BuildAssetInfo>(1000);
// 1. 获取所有收集器收集的资源
bool useAssetDependencyDB = buildParameters.UseAssetDependencyDB;
var collectResult = AssetBundleCollectorSettingData.Setting.BeginCollect(packageName, simulateBuild, useAssetDependencyDB);
List<CollectAssetInfo> allCollectAssets = collectResult.CollectAssets;
// 2. 剔除未被引用的依赖项资源
RemoveZeroReferenceAssets(context, allCollectAssets);
// 3. 录入所有收集器主动收集的资源
foreach (var collectAssetInfo in allCollectAssets)
{
if (allBuildAssetInfos.ContainsKey(collectAssetInfo.AssetInfo.AssetPath))
{
throw new Exception($"Should never get here !");
}
if (collectAssetInfo.CollectorType != ECollectorType.MainAssetCollector)
{
if (collectAssetInfo.AssetTags.Count > 0)
{
collectAssetInfo.AssetTags.Clear();
string warning = BuildLogger.GetErrorMessage(ErrorCode.RemoveInvalidTags, $"Remove asset tags that don't work, see the asset collector type : {collectAssetInfo.AssetInfo.AssetPath}");
BuildLogger.Warning(warning);
}
}
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.CollectorType, collectAssetInfo.BundleName, collectAssetInfo.Address, collectAssetInfo.AssetInfo);
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
allBuildAssetInfos.Add(collectAssetInfo.AssetInfo.AssetPath, buildAssetInfo);
}
// 4. 录入所有收集资源依赖的其它资源
foreach (var collectAssetInfo in allCollectAssets)
{
string bundleName = collectAssetInfo.BundleName;
foreach (var dependAsset in collectAssetInfo.DependAssets)
{
if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out var value))
{
value.AddReferenceBundleName(bundleName);
}
else
{
var buildAssetInfo = new BuildAssetInfo(dependAsset);
buildAssetInfo.AddReferenceBundleName(bundleName);
allBuildAssetInfos.Add(dependAsset.AssetPath, buildAssetInfo);
}
}
}
// 5. 填充所有收集资源的依赖列表
foreach (var collectAssetInfo in allCollectAssets)
{
var dependAssetInfos = new List<BuildAssetInfo>(collectAssetInfo.DependAssets.Count);
foreach (var dependAsset in collectAssetInfo.DependAssets)
{
if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out BuildAssetInfo value))
dependAssetInfos.Add(value);
else
throw new Exception("Should never get here !");
}
allBuildAssetInfos[collectAssetInfo.AssetInfo.AssetPath].SetDependAssetInfos(dependAssetInfos);
}
// 6. 自动收集所有依赖的着色器
if (collectResult.Command.AutoCollectShaders)
{
// 获取着色器打包规则结果
PackRuleResult shaderPackRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
string shaderBundleName = shaderPackRuleResult.GetBundleName(collectResult.Command.PackageName, collectResult.Command.UniqueBundleName);
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
{
if (buildAssetInfo.CollectorType == ECollectorType.None)
{
if (buildAssetInfo.AssetInfo.IsShaderAsset())
{
buildAssetInfo.SetBundleName(shaderBundleName);
}
}
}
}
// 7. 计算共享资源的包名
if (buildParameters.EnableSharePackRule)
{
PreProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
{
if (buildAssetInfo.HasBundleName() == false)
{
ProcessingPackShareBundle(buildParameters, collectResult.Command, buildAssetInfo);
}
}
PostProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
}
// 8. 记录关键信息
context.AssetFileCount = allBuildAssetInfos.Count;
context.Command = collectResult.Command;
// 9. 移除不参与构建的资源
List<BuildAssetInfo> removeBuildList = new List<BuildAssetInfo>();
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
{
if (buildAssetInfo.HasBundleName() == false)
removeBuildList.Add(buildAssetInfo);
}
foreach (var removeValue in removeBuildList)
{
allBuildAssetInfos.Remove(removeValue.AssetInfo.AssetPath);
}
// 10. 构建资源列表
var allPackAssets = allBuildAssetInfos.Values.ToList();
if (allPackAssets.Count == 0)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.PackAssetListIsEmpty, "The pack asset info is empty !");
throw new Exception(message);
}
foreach (var assetInfo in allPackAssets)
{
context.PackAsset(assetInfo);
}
return context;
}
private void RemoveZeroReferenceAssets(BuildMapContext context, List<CollectAssetInfo> allCollectAssets)
{
// 1. 检测依赖资源收集器是否存在
if (allCollectAssets.Exists(x => x.CollectorType == ECollectorType.DependAssetCollector) == false)
return;
// 2. 获取所有主资源的依赖资源集合
HashSet<string> allDependAsset = new HashSet<string>();
foreach (var collectAsset in allCollectAssets)
{
var collectorType = collectAsset.CollectorType;
if (collectorType == ECollectorType.MainAssetCollector || collectorType == ECollectorType.StaticAssetCollector)
{
foreach (var dependAsset in collectAsset.DependAssets)
{
if (allDependAsset.Contains(dependAsset.AssetPath) == false)
allDependAsset.Add(dependAsset.AssetPath);
}
}
}
// 3. 找出所有零引用的依赖资源集合
List<CollectAssetInfo> removeList = new List<CollectAssetInfo>();
foreach (var collectAssetInfo in allCollectAssets)
{
var collectorType = collectAssetInfo.CollectorType;
if (collectorType == ECollectorType.DependAssetCollector)
{
if (allDependAsset.Contains(collectAssetInfo.AssetInfo.AssetPath) == false)
removeList.Add(collectAssetInfo);
}
}
// 4. 移除所有零引用的依赖资源
foreach (var removeValue in removeList)
{
string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundUndependedAsset, $"Found undepended asset and remove it : {removeValue.AssetInfo.AssetPath}");
BuildLogger.Warning(warning);
var independAsset = new ReportIndependAsset();
independAsset.AssetPath = removeValue.AssetInfo.AssetPath;
independAsset.AssetGUID = removeValue.AssetInfo.AssetGUID;
independAsset.AssetType = removeValue.AssetInfo.AssetType.ToString();
independAsset.FileSize = FileUtility.GetFileSize(removeValue.AssetInfo.AssetPath);
context.IndependAssets.Add(independAsset);
allCollectAssets.Remove(removeValue);
}
}
#region
/// <summary>
/// 共享资源打包前置处理
/// </summary>
protected virtual void PreProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
{
}
/// <summary>
/// 共享资源打包机制
/// </summary>
protected virtual void ProcessingPackShareBundle(BuildParameters buildParameters, CollectCommand command, BuildAssetInfo buildAssetInfo)
{
PackRuleResult packRuleResult = GetShareBundleName(buildAssetInfo);
if (packRuleResult.IsValid() == false)
return;
// 处理单个引用的共享资源
if (buildAssetInfo.GetReferenceBundleCount() <= 1)
{
if (buildParameters.SingleReferencedPackAlone == false)
return;
}
// 设置共享资源包名
string shareBundleName = packRuleResult.GetShareBundleName(command.PackageName, command.UniqueBundleName);
buildAssetInfo.SetBundleName(shareBundleName);
}
private PackRuleResult GetShareBundleName(BuildAssetInfo buildAssetInfo)
{
string bundleName = Path.GetDirectoryName(buildAssetInfo.AssetInfo.AssetPath);
PackRuleResult result = new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension);
return result;
}
/// <summary>
/// 共享资源打包后置处理
/// </summary>
protected virtual void PostProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
{
}
#endregion
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public abstract class TaskUpdateBundleInfo
{
public void UpdateBundleInfo(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
int outputNameStyle = (int)buildParametersContext.Parameters.FileNameStyle;
// 1.检测文件名长度
foreach (var bundleInfo in buildMapContext.Collection)
{
// NOTE检测文件名长度不要超过260字符。
string fileName = bundleInfo.BundleName;
if (fileName.Length >= 260)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.CharactersOverTheLimit, $"Bundle file name character count exceeds limit : {fileName}");
throw new Exception(message);
}
}
// 2.更新构建输出的文件路径
foreach (var bundleInfo in buildMapContext.Collection)
{
bundleInfo.BuildOutputFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
if (bundleInfo.Encrypted)
bundleInfo.PackageSourceFilePath = bundleInfo.EncryptedFilePath;
else
bundleInfo.PackageSourceFilePath = bundleInfo.BuildOutputFilePath;
}
// 3.更新文件其它信息
foreach (var bundleInfo in buildMapContext.Collection)
{
bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, context);
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, context);
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, context);
}
// 4.更新补丁包输出的文件路径
foreach (var bundleInfo in buildMapContext.Collection)
{
string bundleName = bundleInfo.BundleName;
string fileHash = bundleInfo.PackageFileHash;
string fileExtension = ManifestTools.GetRemoteBundleFileExtension(bundleName);
string fileName = ManifestTools.GetRemoteBundleFileName(outputNameStyle, bundleName, fileExtension, fileHash);
bundleInfo.PackageDestFilePath = $"{packageOutputDirectory}/{fileName}";
}
}
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context);
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context);
}
}

View File

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

View File

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

View File

@@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskBuilding_BBP : IBuildTask
{
public class BuildResultContext : IContextObject
{
public AssetBundleManifest UnityManifest;
}
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
var builtinBuildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
// 开始构建
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
BuildAssetBundleOptions buildOptions = builtinBuildParameters.GetBundleBuildOptions();
var bundleBuilds = buildMapContext.GetPipelineBuilds(builtinBuildParameters.ReplaceAssetPathWithAddress);
AssetBundleManifest unityManifest = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, bundleBuilds, buildOptions, buildParametersContext.Parameters.BuildTarget);
if (unityManifest == null)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFailed, "UnityEngine build failed !");
throw new Exception(message);
}
// 检测输出目录
string unityOutputManifestFilePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}";
if (System.IO.File.Exists(unityOutputManifestFilePath) == false)
{
string message = BuildLogger.GetErrorMessage(ErrorCode.UnityEngineBuildFatal, $"Not found output {nameof(AssetBundleManifest)} file : {unityOutputManifestFilePath}");
throw new Exception(message);
}
BuildLogger.Log("UnityEngine build success !");
BuildResultContext buildResultContext = new BuildResultContext();
buildResultContext.UnityManifest = unityManifest;
context.SetContextObject(buildResultContext);
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskCopyBuildinFiles_BBP : TaskCopyBuildinFiles, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var manifestContext = context.GetContextObject<ManifestContext>();
if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
{
CopyBuildinFilesToStreaming(buildParametersContext, manifestContext.Manifest);
}
}
}
}

View File

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

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskCreateCatalog_BBP : TaskCreateCatalog, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
if (buildParametersContext.Parameters.BuildinFileCopyOption != EBuildinFileCopyOption.None)
{
CreateCatalogFile(buildParametersContext);
}
}
}
}

View File

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

View File

@@ -0,0 +1,28 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
public class TaskCreateManifest_BBP : TaskCreateManifest, IBuildTask
{
private TaskBuilding_BBP.BuildResultContext _buildResultContext = null;
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var builtinBuildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
bool replaceAssetPathWithAddress = builtinBuildParameters.ReplaceAssetPathWithAddress;
CreateManifestFile(true, true, replaceAssetPathWithAddress, context);
}
protected override string[] GetBundleDepends(BuildContext context, string bundleName)
{
if (_buildResultContext == null)
_buildResultContext = context.GetContextObject<TaskBuilding_BBP.BuildResultContext>();
return _buildResultContext.UnityManifest.GetAllDependencies(bundleName);
}
}
}

View File

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

View File

@@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
namespace YooAsset.Editor
{
public class TaskCreatePackage_BBP : IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
CreatePackagePatch(buildParameters, buildMapContext);
}
/// <summary>
/// 拷贝补丁文件到补丁包目录
/// </summary>
private void CreatePackagePatch(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
{
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
BuildLogger.Log($"Start making patch package: {packageOutputDirectory}");
// 拷贝UnityManifest序列化文件
{
string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}";
string destPath = $"{packageOutputDirectory}/{YooAssetSettings.OutputFolderName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝UnityManifest文本文件
{
string sourcePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}.manifest";
string destPath = $"{packageOutputDirectory}/{YooAssetSettings.OutputFolderName}.manifest";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝所有补丁文件
int progressValue = 0;
int fileTotalCount = buildMapContext.Collection.Count;
foreach (var bundleInfo in buildMapContext.Collection)
{
EditorTools.CopyFile(bundleInfo.PackageSourceFilePath, bundleInfo.PackageDestFilePath, true);
EditorTools.DisplayProgressBar("Copy patch file", ++progressValue, fileTotalCount);
}
EditorTools.ClearProgressBar();
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskCreateReport_BBP : TaskCreateReport, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
var manifestContext = context.GetContextObject<ManifestContext>();
CreateReportFile(buildParameters, buildMapContext, manifestContext);
}
}
}

View File

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

View File

@@ -0,0 +1,13 @@

namespace YooAsset.Editor
{
public class TaskEncryption_BBP : TaskEncryption, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParameters = context.GetContextObject<BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
EncryptingBundleFiles(buildParameters, buildMapContext);
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
using System;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskGetBuildMap_BBP : TaskGetBuildMap, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildMapContext = CreateBuildMap(false, buildParametersContext.Parameters);
context.SetContextObject(buildMapContext);
}
}
}

View File

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

View File

@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskPrepare_BBP : IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters;
var builtinBuildParameters = buildParameters as BuiltinBuildParameters;
// 检测基础构建参数
buildParametersContext.CheckBuildParameters();
// 检测是否有未保存场景
if (EditorTools.HasDirtyScenes())
{
string message = BuildLogger.GetErrorMessage(ErrorCode.FoundUnsavedScene, "Found unsaved scene !");
throw new Exception(message);
}
// 删除包裹目录
if (buildParameters.ClearBuildCacheFiles)
{
string packageRootDirectory = buildParameters.GetPackageRootDirectory();
if (EditorTools.DeleteDirectory(packageRootDirectory))
{
BuildLogger.Log($"Delete package root directory: {packageRootDirectory}");
}
}
// 检测包裹输出目录是否存在
string packageOutputDirectory = buildParameters.GetPackageOutputDirectory();
if (Directory.Exists(packageOutputDirectory))
{
string message = BuildLogger.GetErrorMessage(ErrorCode.PackageOutputDirectoryExists, $"Package outout directory exists: {packageOutputDirectory}");
throw new Exception(message);
}
// 如果输出目录不存在
string pipelineOutputDirectory = buildParameters.GetPipelineOutputDirectory();
if (EditorTools.CreateDirectory(pipelineOutputDirectory))
{
BuildLogger.Log($"Create pipeline output directory: {pipelineOutputDirectory}");
}
// 检测Unity版本
#if UNITY_2021_3_OR_NEWER
string warning = BuildLogger.GetErrorMessage(ErrorCode.RecommendScriptBuildPipeline, $"Starting with UnityEngine2021, recommend use script build pipeline (SBP) !");
BuildLogger.Warning(warning);
#endif
}
}
}

View File

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

View File

@@ -0,0 +1,59 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
namespace YooAsset.Editor
{
public class TaskUpdateBundleInfo_BBP : TaskUpdateBundleInfo, IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
UpdateBundleInfo(context);
}
protected override string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context)
{
var buildResult = context.GetContextObject<TaskBuilding_BBP.BuildResultContext>();
var hash = buildResult.UnityManifest.GetAssetBundleHash(bundleInfo.BundleName);
if (hash.isValid)
{
return hash.ToString();
}
else
{
string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleHash, $"Not found unity bundle hash : {bundleInfo.BundleName}");
throw new Exception(message);
}
}
protected override uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context)
{
string filePath = bundleInfo.BuildOutputFilePath;
if (BuildPipeline.GetCRCForAssetBundle(filePath, out uint crc))
{
return crc;
}
else
{
string message = BuildLogger.GetErrorMessage(ErrorCode.NotFoundUnityBundleCRC, $"Not found unity bundle crc : {bundleInfo.BundleName}");
throw new Exception(message);
}
}
protected override string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildContext context)
{
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileMD5(filePath);
}
protected override uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildContext context)
{
string filePath = bundleInfo.PackageSourceFilePath;
return HashUtility.FileCRC32Value(filePath);
}
protected override long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildContext context)
{
string filePath = bundleInfo.PackageSourceFilePath;
return FileUtility.GetFileSize(filePath);
}
}
}

View File

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

View File

@@ -0,0 +1,68 @@
using System;
using System.Linq;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskVerifyBuildResult_BBP : IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters as BuiltinBuildParameters;
// 验证构建结果
if (buildParameters.VerifyBuildingResult)
{
var buildResultContext = context.GetContextObject<TaskBuilding_BBP.BuildResultContext>();
VerifyingBuildingResult(context, buildResultContext.UnityManifest);
}
}
/// <summary>
/// 验证构建结果
/// </summary>
private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
{
var buildMapContext = context.GetContextObject<BuildMapContext>();
string[] unityBuildContent = unityManifest.GetAllAssetBundles();
// 1. 计划内容
string[] planningContent = buildMapContext.Collection.Select(t => t.BundleName).ToArray();
// 2. 验证差异
List<string> exceptBundleList1 = unityBuildContent.Except(planningContent).ToList();
if (exceptBundleList1.Count > 0)
{
foreach (var exceptBundle in exceptBundleList1)
{
string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
BuildLogger.Warning(warning);
}
string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
throw new Exception(exception);
}
// 3. 验证差异
List<string> exceptBundleList2 = planningContent.Except(unityBuildContent).ToList();
if (exceptBundleList2.Count > 0)
{
foreach (var exceptBundle in exceptBundleList2)
{
string warning = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildBundle, $"Found unintended build bundle : {exceptBundle}");
BuildLogger.Warning(warning);
}
string exception = BuildLogger.GetErrorMessage(ErrorCode.UnintendedBuildResult, $"Unintended build, See the detailed warnings !");
throw new Exception(exception);
}
BuildLogger.Log("Build results verify success!");
}
}
}

Some files were not shown because too many files have changed in this diff Show More