Browse Source

增加花朵和服装的热更新

liuqilin 7 years ago
parent
commit
7805f99536
76 changed files with 1919 additions and 20 deletions
  1. 9 0
      Assets/HotUpdateTest.meta
  2. 1 0
      Assets/HotUpdateTest/MD5.txt
  3. 8 0
      Assets/HotUpdateTest/MD5.txt.meta
  4. 6 0
      Assets/HotUpdateTest/MD5Dictionary.txt
  5. 8 0
      Assets/HotUpdateTest/MD5Dictionary.txt.meta
  6. BIN
      Assets/HotUpdateTest/new_dress_config
  7. 16 0
      Assets/HotUpdateTest/new_dress_config.manifest
  8. 8 0
      Assets/HotUpdateTest/new_dress_config.manifest.meta
  9. 8 0
      Assets/HotUpdateTest/new_dress_config.meta
  10. BIN
      Assets/HotUpdateTest/new_dress_ske
  11. 16 0
      Assets/HotUpdateTest/new_dress_ske.manifest
  12. 8 0
      Assets/HotUpdateTest/new_dress_ske.manifest.meta
  13. 8 0
      Assets/HotUpdateTest/new_dress_ske.meta
  14. BIN
      Assets/HotUpdateTest/new_dress_tex
  15. 27 0
      Assets/HotUpdateTest/new_dress_tex.manifest
  16. 8 0
      Assets/HotUpdateTest/new_dress_tex.manifest.meta
  17. 8 0
      Assets/HotUpdateTest/new_dress_tex.meta
  18. BIN
      Assets/HotUpdateTest/new_flower_config
  19. 16 0
      Assets/HotUpdateTest/new_flower_config.manifest
  20. 8 0
      Assets/HotUpdateTest/new_flower_config.manifest.meta
  21. 8 0
      Assets/HotUpdateTest/new_flower_config.meta
  22. BIN
      Assets/HotUpdateTest/new_flower_tex
  23. 18 0
      Assets/HotUpdateTest/new_flower_tex.manifest
  24. 8 0
      Assets/HotUpdateTest/new_flower_tex.manifest.meta
  25. 8 0
      Assets/HotUpdateTest/new_flower_tex.meta
  26. BIN
      Assets/HotUpdateTest/new_language_config
  27. 18 0
      Assets/HotUpdateTest/new_language_config.manifest
  28. 8 0
      Assets/HotUpdateTest/new_language_config.manifest.meta
  29. 8 0
      Assets/HotUpdateTest/new_language_config.meta
  30. 9 0
      Assets/Resource/Sprite/Editor/HotUpdate/NewFlower.meta
  31. 0 0
      Assets/Resource/Sprite/Editor/HotUpdate/NewFlower/Flower36.png
  32. 0 0
      Assets/Resource/Sprite/Editor/HotUpdate/NewFlower/Flower36.png.meta
  33. 4 4
      Assets/Resource/XML/Config/new_dressRoom_config.xml
  34. 29 0
      Assets/Resource/XML/Config/new_flower_config.xml
  35. 8 0
      Assets/Resource/XML/Config/new_flower_config.xml.meta
  36. BIN
      Assets/Resource/Xlsx/flower_config.xlsx
  37. BIN
      Assets/Resource/Xlsx/new_dressRoom_config.xlsx
  38. BIN
      Assets/Resource/Xlsx/new_flower_config.xlsx
  39. 8 0
      Assets/Resource/Xlsx/new_flower_config.xlsx.meta
  40. 9 0
      Assets/Script/AssetBundleUtility.meta
  41. 74 0
      Assets/Script/AssetBundleUtility/AssetBundleGroup.cs
  42. 12 0
      Assets/Script/AssetBundleUtility/AssetBundleGroup.cs.meta
  43. 28 0
      Assets/Script/AssetBundleUtility/AssetBundleSet.cs
  44. 12 0
      Assets/Script/AssetBundleUtility/AssetBundleSet.cs.meta
  45. 343 0
      Assets/Script/AssetBundleUtility/AssetBundleUtility.cs
  46. 12 0
      Assets/Script/AssetBundleUtility/AssetBundleUtility.cs.meta
  47. 70 0
      Assets/Script/AssetBundleUtility/AssetBundleUtility.prefab
  48. 8 0
      Assets/Script/AssetBundleUtility/AssetBundleUtility.prefab.meta
  49. 9 0
      Assets/Script/AssetBundleUtility/Editor.meta
  50. 99 0
      Assets/Script/AssetBundleUtility/Editor/AssetBundleGroupDrawer.cs
  51. 12 0
      Assets/Script/AssetBundleUtility/Editor/AssetBundleGroupDrawer.cs.meta
  52. 61 0
      Assets/Script/AssetBundleUtility/Editor/AssetBundleUtilityWindow.cs
  53. 12 0
      Assets/Script/AssetBundleUtility/Editor/AssetBundleUtilityWindow.cs.meta
  54. 37 0
      Assets/Script/AssetBundleUtility/Editor/InstanceManager.cs
  55. 12 0
      Assets/Script/AssetBundleUtility/Editor/InstanceManager.cs.meta
  56. 97 0
      Assets/Script/AssetBundleUtility/Editor/InstanceUtility.cs
  57. 12 0
      Assets/Script/AssetBundleUtility/Editor/InstanceUtility.cs.meta
  58. 9 0
      Assets/Script/AssetBundleUtility/Extensions.meta
  59. 275 0
      Assets/Script/AssetBundleUtility/Extensions/ListExtension.cs
  60. 12 0
      Assets/Script/AssetBundleUtility/Extensions/ListExtension.cs.meta
  61. 54 0
      Assets/Script/AssetBundleUtility/Extensions/PathExtension.cs
  62. 12 0
      Assets/Script/AssetBundleUtility/Extensions/PathExtension.cs.meta
  63. 41 0
      Assets/Script/AssetBundleUtility/Extensions/SortExtension.cs
  64. 12 0
      Assets/Script/AssetBundleUtility/Extensions/SortExtension.cs.meta
  65. 24 0
      Assets/Script/AssetBundleUtility/Extensions/StringExtension.cs
  66. 12 0
      Assets/Script/AssetBundleUtility/Extensions/StringExtension.cs.meta
  67. 9 0
      Assets/Script/AssetBundleUtility/MD5Utility.meta
  68. 59 0
      Assets/Script/AssetBundleUtility/MD5Utility/MD5Utility.cs
  69. 12 0
      Assets/Script/AssetBundleUtility/MD5Utility/MD5Utility.cs.meta
  70. 2 0
      Assets/Script/Editor/EditorBundle.cs
  71. 11 1
      Assets/Script/Label/ResourceLabel.cs
  72. 10 8
      Assets/Script/Manage/ConfigManager.cs
  73. 1 1
      Assets/Script/Manage/GardenManager.cs
  74. 8 3
      Assets/Script/Manage/Initializer.cs
  75. 140 0
      Assets/Script/Tool/Bundle.cs
  76. 0 3
      第五期.txt

+ 9 - 0
Assets/HotUpdateTest.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 7abbac64b6299a6418558a47c9ff7fc6
+folderAsset: yes
+timeCreated: 1516870046
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1 - 0
Assets/HotUpdateTest/MD5.txt

@@ -0,0 +1 @@
+AE29F7EE00843A792D96CA02D6907FAA

+ 8 - 0
Assets/HotUpdateTest/MD5.txt.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c8499acffdebb0b48a8e94e0ab8c1226
+timeCreated: 1516870172
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 6 - 0
Assets/HotUpdateTest/MD5Dictionary.txt

@@ -0,0 +1,6 @@
+new_dress_config|F1F0FA4EB0C70A658BB03E935738C422|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_config
+new_dress_ske|531AE05FA301BBAD7B58B532BCD04CFD|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_ske
+new_dress_tex|3060DC78E5C9A8D58CF440C6C66035C4|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_tex
+new_flower_config|0CD417F29E1C7580A742BFC33DAE7DF5|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_flower_config
+new_flower_tex|8640D886CB7D71B5D5EBA8D0FF037573|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_flower_tex
+new_language_config|D7683A0A8867FBC6D32CFF5C9F41BAC4|file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_language_config

+ 8 - 0
Assets/HotUpdateTest/MD5Dictionary.txt.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7fe17844f58d33c4faebe20879be6f88
+timeCreated: 1516870172
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_dress_config


+ 16 - 0
Assets/HotUpdateTest/new_dress_config.manifest

@@ -0,0 +1,16 @@
+ManifestFileVersion: 0
+CRC: 1435180986
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: 8db3b98941bccb5056f9302c1f9ce7b2
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: 1033bf7ddfd4c6d43e7a6382c0a0a61a
+HashAppended: 0
+ClassTypes:
+- Class: 49
+  Script: {instanceID: 0}
+Assets:
+- Assets/Resource/XML/Config/new_dressRoom_config.xml
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_dress_config.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 07f9883b24824ba4eb5565435106c8f1
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_dress_config.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1f03e821e1ebdc24e9f0fa80e2efcc0c
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_dress_ske


+ 16 - 0
Assets/HotUpdateTest/new_dress_ske.manifest

@@ -0,0 +1,16 @@
+ManifestFileVersion: 0
+CRC: 1214458779
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: 4e04ffbb6a9f00a00f72656f4e551357
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: 1033bf7ddfd4c6d43e7a6382c0a0a61a
+HashAppended: 0
+ClassTypes:
+- Class: 49
+  Script: {instanceID: 0}
+Assets:
+- Assets/Resource/Sprite/Editor/HotUpdate/NewDress/Dress_ske.json
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_dress_ske.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c055676457b3c9746a9fadac68a274f0
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_dress_ske.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 46e6bdba81cd7ce4695e7e3b87409b5b
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_dress_tex


+ 27 - 0
Assets/HotUpdateTest/new_dress_tex.manifest

@@ -0,0 +1,27 @@
+ManifestFileVersion: 0
+CRC: 3005921567
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: 3b0a4652df90c0e3947302bacdcbdeb9
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: afff6fb5165c398f343463019e0d022b
+HashAppended: 0
+ClassTypes:
+- Class: 28
+  Script: {instanceID: 0}
+- Class: 49
+  Script: {instanceID: 0}
+- Class: 213
+  Script: {instanceID: 0}
+Assets:
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u4E0B\u886314_tex.json"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u4E0A\u886314.png"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u5934\u53D114\uFF08\u7C89\u8272\uFF09.png"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u88C5\u997014_tex.json"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u4E0A\u886314_tex.json"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u88C5\u997014.png"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u5934\u53D114\uFF08\u7C89\u8272\uFF09_tex.json"
+- "Assets/Resource/Sprite/Editor/HotUpdate/NewDress/\u4E0B\u886314.png"
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_dress_tex.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3fc4ae25f9a5ed447b41aec2359d88c7
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_dress_tex.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: de2a2ad7ab38f9e4b80402dc8153ccbe
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_flower_config


+ 16 - 0
Assets/HotUpdateTest/new_flower_config.manifest

@@ -0,0 +1,16 @@
+ManifestFileVersion: 0
+CRC: 2514910370
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: cdf89807a0f3410ee523aeeb99db94ff
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: 1033bf7ddfd4c6d43e7a6382c0a0a61a
+HashAppended: 0
+ClassTypes:
+- Class: 49
+  Script: {instanceID: 0}
+Assets:
+- Assets/Resource/XML/Config/new_flower_config.xml
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_flower_config.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c60a0da0ce4bca04aa79b2bad95f89ba
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_flower_config.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2322ebf659ac53340bfdc21c831c6f31
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_flower_tex


+ 18 - 0
Assets/HotUpdateTest/new_flower_tex.manifest

@@ -0,0 +1,18 @@
+ManifestFileVersion: 0
+CRC: 3681479126
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: 545d684925f1aaf4c2103de315737004
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: 4d24bf54f46935ed9e6cf78ac481bb9d
+HashAppended: 0
+ClassTypes:
+- Class: 28
+  Script: {instanceID: 0}
+- Class: 213
+  Script: {instanceID: 0}
+Assets:
+- Assets/Resource/Sprite/Editor/HotUpdate/NewFlower/Flower36.png
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_flower_tex.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a794813af6ecaf149a0f5a6801806abe
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_flower_tex.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b2d57842484c01a4ea3a286143207ee1
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Assets/HotUpdateTest/new_language_config


+ 18 - 0
Assets/HotUpdateTest/new_language_config.manifest

@@ -0,0 +1,18 @@
+ManifestFileVersion: 0
+CRC: 3985457301
+Hashes:
+  AssetFileHash:
+    serializedVersion: 2
+    Hash: 1f416e3ef7e6b37669d8ceee5191d980
+  TypeTreeHash:
+    serializedVersion: 2
+    Hash: 1033bf7ddfd4c6d43e7a6382c0a0a61a
+HashAppended: 0
+ClassTypes:
+- Class: 49
+  Script: {instanceID: 0}
+Assets:
+- Assets/Resource/XML/lan/new_ChineseSimplified.xml
+- Assets/Resource/XML/lan/new_ChineseTraditional.xml
+- Assets/Resource/XML/lan/new_English.xml
+Dependencies: []

+ 8 - 0
Assets/HotUpdateTest/new_language_config.manifest.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ca10b26506fe3e14eab1e2d8186fb97e
+timeCreated: 1516869986
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/HotUpdateTest/new_language_config.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5b03cd71e42736741a067becf4ad756b
+timeCreated: 1516869986
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Resource/Sprite/Editor/HotUpdate/NewFlower.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 46b274c8414a222419da71c9a4da16df
+folderAsset: yes
+timeCreated: 1516869190
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
Assets/Resource/Sprite/Mobile/Garden/Flower36.png → Assets/Resource/Sprite/Editor/HotUpdate/NewFlower/Flower36.png


+ 0 - 0
Assets/Resource/Sprite/Mobile/Garden/Flower36.png.meta → Assets/Resource/Sprite/Editor/HotUpdate/NewFlower/Flower36.png.meta


+ 4 - 4
Assets/Resource/XML/Config/new_dressRoom_config.xml

@@ -1,8 +1,8 @@
 <data>
-  <item id="31" jump_frequency="" type="1" index="29" bodypart="1" level="50" buy_currency="2" buy_amt="500" buy_advance_currency="" buy_advance_amt="" pixelSize="90" iconOffset="" icon1offset="" icon2offset="" spriteName="头发14(粉色)" spriteAlpha="" armatureName="头发14(粉色)" extraBodypart="" extraArmatureName="" ignore="1" />
-  <item id="218" jump_frequency="" type="3" index="17" bodypart="2" level="50" buy_currency="2" buy_amt="2000" buy_advance_currency="" buy_advance_amt="" pixelSize="100" iconOffset="" icon1offset="" icon2offset="" spriteName="下衣14" spriteAlpha="" armatureName="下衣14" extraBodypart="" extraArmatureName="" ignore="1" />
-  <item id="613" jump_frequency="" type="4" index="12" bodypart="4" level="50" buy_currency="2" buy_amt="450" buy_advance_currency="" buy_advance_amt="" pixelSize="80" iconOffset="" icon1offset="" icon2offset="" spriteName="装饰14" spriteAlpha="" armatureName="装饰14" extraBodypart="" extraArmatureName="" ignore="1" />
-  <item id="818" jump_frequency="" type="2" index="17" bodypart="5" level="50" buy_currency="2" buy_amt="750" buy_advance_currency="" buy_advance_amt="" pixelSize="110" iconOffset="" icon1offset="" icon2offset="" spriteName="上衣14" spriteAlpha="" armatureName="上衣14" extraBodypart="10,9" extraArmatureName="" ignore="1" />
+  <item id="31" jump_frequency="" type="1" index="29" bodypart="1" level="50" buy_currency="2" buy_amt="500" buy_advance_currency="" buy_advance_amt="" pixelSize="90" iconOffset="" icon1offset="" icon2offset="" spriteName="头发14(粉色)" spriteAlpha="" armatureName="头发14(粉色)" extraBodypart="" extraArmatureName="" ignore="0" />
+  <item id="218" jump_frequency="" type="3" index="17" bodypart="2" level="50" buy_currency="2" buy_amt="2000" buy_advance_currency="" buy_advance_amt="" pixelSize="100" iconOffset="" icon1offset="" icon2offset="" spriteName="下衣14" spriteAlpha="" armatureName="下衣14" extraBodypart="" extraArmatureName="" ignore="0" />
+  <item id="613" jump_frequency="" type="4" index="12" bodypart="4" level="50" buy_currency="2" buy_amt="450" buy_advance_currency="" buy_advance_amt="" pixelSize="80" iconOffset="" icon1offset="" icon2offset="" spriteName="装饰14" spriteAlpha="" armatureName="装饰14" extraBodypart="" extraArmatureName="" ignore="0" />
+  <item id="818" jump_frequency="" type="2" index="17" bodypart="5" level="50" buy_currency="2" buy_amt="750" buy_advance_currency="" buy_advance_amt="" pixelSize="110" iconOffset="" icon1offset="" icon2offset="" spriteName="上衣14" spriteAlpha="" armatureName="上衣14" extraBodypart="10,9" extraArmatureName="" ignore="0" />
   <comment>
     <id>
 id

+ 29 - 0
Assets/Resource/XML/Config/new_flower_config.xml

@@ -0,0 +1,29 @@
+<data>
+  <comment>
+    <id>
+id
+</id>
+    <name>
+名称
+</name>
+    <desc>
+描述
+</desc>
+    <unlock_ahead_cur>
+提前解锁
+消耗货币
+</unlock_ahead_cur>
+    <unlock_ahead>
+提前解锁消耗的货币
+</unlock_ahead>
+    <icon>
+图标
+</icon>
+    <anim>
+场景物件
+</anim>
+    <flower_coin_buff>
+种花金币加成
+</flower_coin_buff>
+  </comment>
+</data>

+ 8 - 0
Assets/Resource/XML/Config/new_flower_config.xml.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 017f420931600084280cc54894830112
+timeCreated: 1516869282
+licenseType: Pro
+TextScriptImporter:
+  userData: 
+  assetBundleName: new_flower_config
+  assetBundleVariant: 

BIN
Assets/Resource/Xlsx/flower_config.xlsx


BIN
Assets/Resource/Xlsx/new_dressRoom_config.xlsx


BIN
Assets/Resource/Xlsx/new_flower_config.xlsx


+ 8 - 0
Assets/Resource/Xlsx/new_flower_config.xlsx.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a3d699c1552e746479c2a54f423c6153
+timeCreated: 1516869245
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Script/AssetBundleUtility.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: f677b4aea741bf04a8887cbb2b8dfad4
+folderAsset: yes
+timeCreated: 1516862856
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 74 - 0
Assets/Script/AssetBundleUtility/AssetBundleGroup.cs

@@ -0,0 +1,74 @@
+namespace assetBundleUtility
+{
+
+
+#if UNITY_EDITOR
+	using System;
+	using System.Collections.Generic;
+	using System.IO;
+	using System.Linq;
+	using UnityEditor;
+	
+	[Serializable]
+	public class AssetBundleGroup
+	{
+        #region Config
+
+        public string MD5FileName = "MD5.txt";
+        public string MD5DictionaryFileName = "MD5Dictionary.txt";
+        public string OutputPath;
+        public List<AssetBundleSet> AssetBundleSets = new List<AssetBundleSet>();
+
+        //CustomPropertyDrawer使用
+        [NonSerialized] public float TotalHeight;
+
+        #endregion
+	
+	    public void CreateMD5FileAndMD5DictionaryFile()
+	    {
+	        string md5FilePath = CheckOutputPath(OutputPath, MD5FileName);
+	        string md5DictionaryFilePath = CheckOutputPath(OutputPath, MD5DictionaryFileName);
+	
+	        List<AssetBundleSet> assetBundleSets = new List<AssetBundleSet>();
+	        for (int i = 0; i < AssetBundleSets.Count; i++)
+	        {
+	            AssetBundleSet assetBundleSet = AssetBundleSets[i];
+	            if (assetBundleSet.Object == null) continue;
+	            assetBundleSet.Name = assetBundleSet.Object.name;
+	            assetBundleSet.StreamingPath = AssetDatabase.GetAssetPath(assetBundleSet.Object);
+	            assetBundleSet.MD5 = MD5Utility.GetMD5StringFromPath(assetBundleSet.StreamingPath);
+	            assetBundleSets.Add(assetBundleSet);
+	        }
+
+            assetBundleSets.MySort((bundleSet0, bundleSet1) => SortExtension.CompareASCII(bundleSet1.Name, bundleSet0.Name));
+            string md5Dictionary = AssetBundleUtility.CreateMD5Dictionary(assetBundleSets, false);
+	        byte[] bytes = MD5Utility.GetMD5(md5Dictionary);
+	        string md5 = MD5Utility.BytesToString(bytes);
+	        File.WriteAllText(md5FilePath, md5);
+	        md5Dictionary = AssetBundleUtility.CreateMD5Dictionary(assetBundleSets, true);
+	        File.WriteAllText(md5DictionaryFilePath, md5Dictionary);
+
+	        AssetDatabase.Refresh();
+	    }
+	
+	    private string CheckOutputPath(string path, string name)
+	    {
+	        string directory = path.TrimEnd('/', '\\') + Path.DirectorySeparatorChar;
+	
+	        if (directory == Path.DirectorySeparatorChar.ToString() || !Directory.Exists(directory))
+	        {
+	            throw new Exception("文件夹不存在");
+	        }
+	
+	        if (string.IsNullOrEmpty(name) || name.Any(Path.GetInvalidFileNameChars().Contains))
+	        {
+	            throw new Exception("文件名包含无效字符");
+	        }
+	
+	        return $"{path}{Path.DirectorySeparatorChar}{name}";
+	    }
+	}
+#endif
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/AssetBundleGroup.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: aba9a24d837c3cb4a93f3771f4c3db04
+timeCreated: 1512630945
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 28 - 0
Assets/Script/AssetBundleUtility/AssetBundleSet.cs

@@ -0,0 +1,28 @@
+namespace assetBundleUtility
+{
+
+
+	using System;
+
+	using UnityEngine;
+
+    using Object = UnityEngine.Object;
+	
+	[Serializable]
+	public class AssetBundleSet
+	{
+	    [NonSerialized] public string Name;
+	    [NonSerialized] public string MD5;
+	    [NonSerialized] public string StreamingPath;
+	    [NonSerialized] public string PersistentPath;
+	    [NonSerialized] public AssetBundle AssetBundle;
+	    [NonSerialized] public Action<AssetBundleSet> GetSucceedCallback;  //加载/下载成功后的回调
+	    [NonSerialized] public Action<AssetBundleSet, string> GetFailedCallback;  //加载/下载失败后的回调
+	
+	    //EditorWindow使用 用于自动生成MD5File和MD5DictionaryFile
+	    public Object Object;
+	    public string URL;
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/AssetBundleSet.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ae6885ce762ef634a9754a71cc7c77e7
+timeCreated: 1512907365
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 343 - 0
Assets/Script/AssetBundleUtility/AssetBundleUtility.cs

@@ -0,0 +1,343 @@
+namespace assetBundleUtility
+{
+
+
+	using System;
+	using System.Collections;
+	using System.Collections.Generic;
+	using System.IO;
+	using System.Linq;
+	using System.Text;
+
+	using UnityEngine;
+	
+	public class AssetBundleUtility : MonoBehaviour
+	{
+	    #region Config
+		
+	    public static AssetBundleUtility Instance
+	    {
+	        get
+	        {
+	            if (instance == null)
+	            {
+	                GameObject go = new GameObject("AssetBundleUtility");
+	                DontDestroyOnLoad(go);
+	                instance = go.AddComponent<AssetBundleUtility>();
+	            }
+	            return instance;
+	        }
+	    }
+	    public static AssetBundleUtility instance;
+
+        private static string FTPPrefix = "file://";
+
+#if UNITY_EDITOR
+        public List<AssetBundleGroup> AssetBundleGroups;
+#endif
+
+        #endregion
+
+        public static string GetMD5OfAssetBundleSets(List<AssetBundleSet> assetBundleSets)
+	    {
+	        string md5Dictionary = CreateMD5Dictionary(assetBundleSets, false);
+	        byte[] bytes = MD5Utility.GetMD5(md5Dictionary);
+	        string md5 = MD5Utility.BytesToString(bytes);
+	        return md5;
+	    }
+
+        public static string CreateMD5Dictionary(List<AssetBundleSet> assetBundleSets, bool includeURL)
+        {
+            StringBuilder stringBuilder = new StringBuilder();
+            for (int i = 0; i < assetBundleSets.Count; i++)
+            {
+                stringBuilder.Append($"{assetBundleSets[i].Name}|{assetBundleSets[i].MD5}");
+                if (includeURL)
+                {
+                    stringBuilder.Append($"|{assetBundleSets[i].URL}");
+                }
+                if (i < assetBundleSets.Count - 1)
+                {
+                    stringBuilder.Append("\r\n");
+                }
+            }
+            return stringBuilder.ToString();
+        }
+
+        private static List<AssetBundleSet> ParseMD5Dictionary(string md5Dictionary)
+        {
+            List<AssetBundleSet> assetBundleSets = new List<AssetBundleSet>();
+            List<string> items = md5Dictionary.Trim().Split(new[] { "\r\n" }, StringSplitOptions.None).ToList();
+            for (int i = 0; i < items.Count; i++)
+            {
+                AssetBundleSet assetBundleSet = new AssetBundleSet();
+                string[] strings = items[i].Split('|');
+                assetBundleSet.Name = strings[0];
+                assetBundleSet.MD5 = strings[1];
+                assetBundleSet.URL = strings[2];
+                assetBundleSets.Add(assetBundleSet);
+            }
+            return assetBundleSets;
+        }
+
+
+        /// <summary>
+        ///加载AssetBundle
+        /// </summary>
+        /// <param name="allSucceedCallback">所有AssetBundle都加载成功后的回调</param>
+        /// <param name="haveFailedCallback">任意一个AssetBundle加载失败后的回调 如果有多个AssetBundle加载失败 也只回调一次</param>
+        /// <param name="getSucceedCallback">每个AssetBundle加载成功后的回调</param>
+        /// <param name="getFailedCallback">每个AssetBundle加载失败后的回调</param>
+        public static void LoadAllAssetBundle(List<AssetBundleSet> assetBundleSets, Action allSucceedCallback, Action haveFailedCallback, Action<AssetBundleSet> getSucceedCallback, Action<AssetBundleSet, string> getFailedCallback)
+	    {
+            List<AssetBundleSet> staleAssetBundleSets = new List<AssetBundleSet>();
+            foreach (var assetBundleSet in assetBundleSets)
+            {
+                assetBundleSet.GetSucceedCallback = getSucceedCallback;
+                assetBundleSet.GetFailedCallback = getFailedCallback;
+                //Debug.Log($"UpToDateAssetBundleSet : {assetBundleSet.Name}");
+            }
+            LoadAndDownloadAssetBundles(staleAssetBundleSets, assetBundleSets, allSucceedCallback, haveFailedCallback);
+        }
+
+        /// <summary>
+        ///加载/下载AssetBundle
+        /// </summary>
+        /// <param name="persistentFolder">下载后AssetBundle存放的目录</param>
+        /// <param name="allSucceedCallback">所有AssetBundle都加载/下载成功后的回调</param>
+        /// <param name="haveFailedCallback">任意一个AssetBundle加载/下载失败后的回调 如果有多个AssetBundle加载/下载失败 也只回调一次</param>
+        /// <param name="getSucceedCallback">每个AssetBundle加载/下载成功后的回调</param>
+        /// <param name="getFailedCallback">每个AssetBundle加载/下载失败后的回调</param>
+        public static void UpdateAllAssetBundle(string md5Dictionary, string persistentFolder, List<AssetBundleSet> assetBundleSets, Action allSucceedCallback, Action haveFailedCallback, Action<AssetBundleSet> getSucceedCallback, Action<AssetBundleSet, string> getFailedCallback)
+        {
+            List<AssetBundleSet> staleAssetBundleSets = new List<AssetBundleSet>();
+            List<AssetBundleSet> upToDateAssetBundleSets = new List<AssetBundleSet>();
+            GetStaleAndUpToDateAssetBundleSets(md5Dictionary, persistentFolder, assetBundleSets, staleAssetBundleSets, upToDateAssetBundleSets);
+            foreach (var staleAssetBundleSet in staleAssetBundleSets)
+            {
+                staleAssetBundleSet.GetSucceedCallback = getSucceedCallback;
+                staleAssetBundleSet.GetFailedCallback = getFailedCallback;
+                //Debug.Log($"StaleAssetBundleSet : {staleAssetBundleSet.Name}");
+            }
+            foreach (var upToDateAssetBundleSet in upToDateAssetBundleSets)
+            {
+                upToDateAssetBundleSet.GetSucceedCallback = getSucceedCallback;
+                upToDateAssetBundleSet.GetFailedCallback = getFailedCallback;
+                //Debug.Log($"UpToDateAssetBundleSet : {upToDateAssetBundleSet.Name}");
+            }
+            LoadAndDownloadAssetBundles(staleAssetBundleSets, upToDateAssetBundleSets, allSucceedCallback, haveFailedCallback);
+        }
+
+        private static void GetStaleAndUpToDateAssetBundleSets(string md5Dictionary, string persistentFolder, List<AssetBundleSet> assetBundleSets, List<AssetBundleSet> staleAssetBundleSets, List<AssetBundleSet> upToDateAssetBundleSets)
+        {
+            List<AssetBundleSet> serverAssetBundleSets = ParseMD5Dictionary(md5Dictionary);
+            foreach (var serverAssetBundleSet in serverAssetBundleSets)
+            {
+                bool missingFlag = true;
+                foreach (var assetBundleSet in assetBundleSets)
+                {
+                    if (assetBundleSet.Name != serverAssetBundleSet.Name) continue;
+                    if (assetBundleSet.MD5 == serverAssetBundleSet.MD5)
+                    {
+                        missingFlag = false;
+                        upToDateAssetBundleSets.Add(assetBundleSet);
+                        break;
+                    }
+                    else
+                    {
+                        assetBundleSet.URL = serverAssetBundleSet.URL;
+                        staleAssetBundleSets.Add(assetBundleSet);
+                        missingFlag = false;
+                        break;
+                    }
+                }
+                if (missingFlag)
+                {
+                    serverAssetBundleSet.PersistentPath = $"{persistentFolder}{Path.DirectorySeparatorChar}{serverAssetBundleSet.Name}";
+                    staleAssetBundleSets.Add(serverAssetBundleSet);
+                }
+            }
+        }
+
+        private static void LoadAndDownloadAssetBundles(List<AssetBundleSet> staleAssetBundleSets, List<AssetBundleSet> upToDateAssetBundleSets, Action allSucceedCallback, Action haveFailedCallback)
+	    {
+	        int remainAmount = upToDateAssetBundleSets.Count + staleAssetBundleSets.Count;
+	        bool failedFlag = false;
+	        foreach (var assetBundleSets in upToDateAssetBundleSets)
+	        {
+	            LoadBundle
+	            (
+	                assetBundleSets,
+	                () => LoadAndDownloadAssetBundleSucceedCallback(ref remainAmount, allSucceedCallback),
+                    () => LoadAndDownloadAssetBundleFailedCallback(ref failedFlag, haveFailedCallback)
+                );
+	        }
+	        foreach (var assetBundleSets in staleAssetBundleSets)
+	        {
+	            DownloadBundle
+	            (
+	                assetBundleSets,
+	                () => LoadAndDownloadAssetBundleSucceedCallback(ref remainAmount, allSucceedCallback),
+	                () => LoadAndDownloadAssetBundleFailedCallback(ref failedFlag, haveFailedCallback)
+	            );
+	        }
+	    }
+
+        private static void LoadAndDownloadAssetBundleSucceedCallback(ref int remainAmount,  Action allSucceedCallback)
+        {
+            if (--remainAmount == 0) allSucceedCallback.Invoke();
+        }
+
+        private static void LoadAndDownloadAssetBundleFailedCallback(ref bool failedFlag, Action haveFailedCallback)
+        {
+            if (failedFlag) return;
+            failedFlag = true;
+            haveFailedCallback.Invoke();
+        }
+
+
+	    /// <summary>
+	    /// 
+	    /// </summary>
+	    /// <param name="persistentFolder">更新后AssetBundle存放的目录</param>
+	    /// <param name="streamingFolder">源AssetBundle存放的目录</param>
+	    /// <returns></returns>
+	    public static List<AssetBundleSet> GetAssetBundleSetsFromFolders(string persistentFolder, string streamingFolder)
+	    {
+	        List<AssetBundleSet> persistentAssetBundleSets = new List<AssetBundleSet>();
+	        if (Directory.Exists(persistentFolder))
+	        {
+	            persistentAssetBundleSets.AddRange(GetAllAssetBundleSetFromFolder(persistentFolder, persistentFolder));
+	        }
+	        List<AssetBundleSet> streamingAssetBundleSets = new List<AssetBundleSet>();
+	        streamingAssetBundleSets.AddRange(GetAllAssetBundleSetFromFolder(streamingFolder, persistentFolder));
+
+            for (int i = 0; i < streamingAssetBundleSets.Count; i++)
+	        {
+	            foreach (var persistentAssetBundleSet in persistentAssetBundleSets)
+	            {
+	                if (streamingAssetBundleSets[i].Name != persistentAssetBundleSet.Name) continue;
+	                streamingAssetBundleSets.RemoveAt(i--);
+                    break;
+	            }
+	        }
+
+	        List<AssetBundleSet> assetBundleSets = new List<AssetBundleSet>();
+	        assetBundleSets.AddRange(streamingAssetBundleSets);
+	        assetBundleSets.AddRange(persistentAssetBundleSets);
+	        for (int i = 0; i < assetBundleSets.Count; i++)
+	        {
+	            assetBundleSets[i].StreamingPath = assetBundleSets[i].StreamingPath.Replace("\\", Path.DirectorySeparatorChar.ToString()).Replace("/", Path.DirectorySeparatorChar.ToString());
+            }
+            assetBundleSets.MySort((bundleSet0, bundleSet1) => SortExtension.CompareASCII(bundleSet1.Name, bundleSet0.Name));
+            return assetBundleSets;
+	    }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="folder">源AssetBundle存放的目录</param>
+        /// <param name="persistentFolder">更新后AssetBundle存放的目录</param>
+        /// <returns></returns>
+	    private static List<AssetBundleSet> GetAllAssetBundleSetFromFolder(string folder, string persistentFolder)
+	    {
+	        List<string> pathes = new List<string>();
+	        List<string> names = new List<string>();
+	        List<string> md5s = new List<string>();
+	        List<string> savePathes = new List<string>();
+	        pathes.AddRange(Directory.GetFiles(folder, "*", SearchOption.AllDirectories));
+	        RemoveMetaFilePath(pathes);
+            RemoveManifestFilePath(pathes);
+            names = pathes.GetAllFileNameFromPath();
+	        md5s = MD5Utility.GetAllMD5StringFromPath(pathes);
+	        savePathes = pathes.ReplaceAll(folder, persistentFolder);
+	
+	        for (int i = 0; i < pathes.Count; i++)
+	        {
+	            pathes[i] = pathes[i].Replace("\\", Path.DirectorySeparatorChar.ToString()).Replace("/", Path.DirectorySeparatorChar.ToString());
+	        }
+	
+	        List<AssetBundleSet> results = new List<AssetBundleSet>();
+	        for (int i = 0; i < names.Count; i++)
+	        {
+	            AssetBundleSet assetBundleSet = new AssetBundleSet();
+	            assetBundleSet.StreamingPath = pathes[i];
+	            assetBundleSet.Name = names[i];
+	            assetBundleSet.MD5 = md5s[i];
+	            assetBundleSet.PersistentPath = savePathes[i];
+	            results.Add(assetBundleSet);
+	        }
+	        return results;
+	    }
+	
+	    private static void RemoveMetaFilePath(List<string> pathes)
+	    {
+	        for (int i = 0; i < pathes.Count; i++)
+	        {
+	            if (pathes[i].EndsWith(".meta"))
+	            {
+	                pathes.RemoveAt(i--);
+	            }
+	        }
+	    }
+
+        private static void RemoveManifestFilePath(List<string> pathes)
+        {
+            for (int i = 0; i < pathes.Count; i++)
+            {
+                if (pathes[i].EndsWith(".manifest"))
+                {
+                    pathes.RemoveAt(i--);
+                }
+            }
+        }
+
+
+        public static void LoadBundle(AssetBundleSet assetBundleSet, Action succeedCallback, Action failedCallback)
+	    {
+	        Instance.StartCoroutine(loadBundle(assetBundleSet, succeedCallback, failedCallback));
+	    }
+
+        public static void DownloadBundle(AssetBundleSet assetBundleSet, Action succeedCallback, Action failedCallback)
+        {
+            Instance.StartCoroutine(downloadBundle(assetBundleSet, succeedCallback, failedCallback));
+        }
+
+        private static IEnumerator loadBundle(AssetBundleSet assetBundleSet, Action succeedCallback, Action failedCallback)
+	    {
+	        WWW www = new WWW(FTPPrefix + assetBundleSet.StreamingPath);
+	        yield return www;
+	        if (!string.IsNullOrEmpty(www.error))
+	        {
+                assetBundleSet.GetFailedCallback.Invoke(assetBundleSet, www.error);
+                failedCallback.Invoke();
+                yield break;
+	        }
+	        assetBundleSet.AssetBundle = www.assetBundle;
+            assetBundleSet.GetSucceedCallback.Invoke(assetBundleSet);
+            succeedCallback.Invoke();
+        }
+	
+	    private static IEnumerator downloadBundle(AssetBundleSet assetBundleSet, Action succeedCallback, Action failedCallback)
+	    {
+	        WWW www = new WWW(assetBundleSet.URL);
+	        yield return www;
+	        if (!string.IsNullOrEmpty(www.error))
+	        {
+                assetBundleSet.GetFailedCallback.Invoke(assetBundleSet, www.error);
+                failedCallback.Invoke();
+                yield break;
+	        }
+	        if (!Directory.Exists(assetBundleSet.PersistentPath))
+	        {
+	            Directory.CreateDirectory(Path.GetDirectoryName(assetBundleSet.PersistentPath));
+	        }
+	        File.WriteAllBytes(assetBundleSet.PersistentPath, www.bytes);
+	        assetBundleSet.AssetBundle = www.assetBundle;
+            assetBundleSet.GetSucceedCallback.Invoke(assetBundleSet);
+            succeedCallback.Invoke();
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/AssetBundleUtility.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fb4361360f79a454da57450b6abd0d44
+timeCreated: 1512023702
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 70 - 0
Assets/Script/AssetBundleUtility/AssetBundleUtility.prefab

@@ -0,0 +1,70 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &100100000
+Prefab:
+  m_ObjectHideFlags: 1
+  serializedVersion: 2
+  m_Modification:
+    m_TransformParent: {fileID: 0}
+    m_Modifications: []
+    m_RemovedComponents: []
+  m_ParentPrefab: {fileID: 0}
+  m_RootGameObject: {fileID: 1594177319052792}
+  m_IsPrefabParent: 1
+--- !u!1 &1594177319052792
+GameObject:
+  m_ObjectHideFlags: 0
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 100100000}
+  serializedVersion: 5
+  m_Component:
+  - component: {fileID: 4977813053446552}
+  - component: {fileID: 114188865886771778}
+  m_Layer: 0
+  m_Name: AssetBundleUtility
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &4977813053446552
+Transform:
+  m_ObjectHideFlags: 1
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 100100000}
+  m_GameObject: {fileID: 1594177319052792}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &114188865886771778
+MonoBehaviour:
+  m_ObjectHideFlags: 1
+  m_PrefabParentObject: {fileID: 0}
+  m_PrefabInternal: {fileID: 100100000}
+  m_GameObject: {fileID: 1594177319052792}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fb4361360f79a454da57450b6abd0d44, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  AssetBundleGroups:
+  - MD5FileName: MD5.txt
+    MD5DictionaryFileName: MD5Dictionary.txt
+    OutputPath: Assets\HotUpdateTest
+    AssetBundleSets:
+    - Object: {fileID: 102900000, guid: 1f03e821e1ebdc24e9f0fa80e2efcc0c, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_config
+    - Object: {fileID: 102900000, guid: 46e6bdba81cd7ce4695e7e3b87409b5b, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_ske
+    - Object: {fileID: 102900000, guid: de2a2ad7ab38f9e4b80402dc8153ccbe, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_dress_tex
+    - Object: {fileID: 102900000, guid: 2322ebf659ac53340bfdc21c831c6f31, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_flower_config
+    - Object: {fileID: 102900000, guid: b2d57842484c01a4ea3a286143207ee1, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_flower_tex
+    - Object: {fileID: 102900000, guid: 5b03cd71e42736741a067becf4ad756b, type: 3}
+      URL: file://E:\UnityProject\Garden5\Assets\HotUpdateTest\new_language_config

+ 8 - 0
Assets/Script/AssetBundleUtility/AssetBundleUtility.prefab.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5cb4f5e53f70a6f499cb8ed2ce5d58b8
+timeCreated: 1512030031
+licenseType: Pro
+NativeFormatImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Script/AssetBundleUtility/Editor.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 56e60d3cf16b4da4e97ba86936b2ddf9
+folderAsset: yes
+timeCreated: 1512023745
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 99 - 0
Assets/Script/AssetBundleUtility/Editor/AssetBundleGroupDrawer.cs

@@ -0,0 +1,99 @@
+namespace assetBundleUtility
+{
+
+
+	using System;
+
+	using UnityEditor;
+	using UnityEngine;
+	
+	[CustomPropertyDrawer(typeof(AssetBundleGroup))]
+	public class AssetBundleGroupDrawer : PropertyDrawer
+	{
+	    #region Config
+	
+	    private float LineSpan = 2;
+	    private float LineHeight = 16;
+	    private float ButtonSpan = 4;
+	    private float ButtonHeight = 32;
+	
+	    private AssetBundleGroup Instance;
+	    private SerializedProperty MD5FileName;
+	    private SerializedProperty MD5DictionaryFileName;
+	    private SerializedProperty OutputPath;
+	    private SerializedProperty AssetBundleSets;
+	
+	    #endregion
+	
+	    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+	    {
+	        Instance = (AssetBundleGroup)InstanceUtility.GetObject(fieldInfo, property);
+
+	        return Instance.TotalHeight;
+        }
+	
+	    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+	    {
+	        Instance = (AssetBundleGroup) InstanceUtility.GetObject(fieldInfo, property);
+	        MD5FileName = property.FindPropertyRelative("MD5FileName");
+	        MD5DictionaryFileName = property.FindPropertyRelative("MD5DictionaryFileName");
+	        OutputPath = property.FindPropertyRelative("OutputPath");
+	        AssetBundleSets = property.FindPropertyRelative("AssetBundleSets");
+	
+	        float originY = position.y;
+	
+	        position.height = LineHeight;
+	
+	        EditorGUI.indentLevel++;
+	        position = DrawProperty(position, MD5FileName);
+	        position = DrawProperty(position, MD5DictionaryFileName);
+	        position = DrawProperty(position, OutputPath);
+	        position = DrawPropertys(position, AssetBundleSets);
+	        position = DrawButton(position, "Create MD5File And MD5DictionaryFile", Instance.CreateMD5FileAndMD5DictionaryFile);
+	
+	        Instance.TotalHeight = position.y - originY;
+        }
+	
+	    private Rect DrawButton(Rect position, string name, Action OnClick)
+	    {
+	        Rect contentPosition = position;
+	        contentPosition.height = ButtonHeight;
+	        if (GUI.Button(contentPosition, name))
+	        {
+	            OnClick.Invoke();
+	        }
+	        position.y += ButtonHeight + ButtonSpan;
+	        return position;
+	    }
+	
+	    private Rect DrawProperty(Rect position, SerializedProperty property)
+	    {
+	        Rect contentPosition = position;
+	        contentPosition.height = LineHeight;
+	        contentPosition = EditorGUI.PrefixLabel(contentPosition, new GUIContent(property.displayName));
+	        EditorGUI.PropertyField(contentPosition, property, GUIContent.none);
+	        position.y += LineHeight + LineSpan;
+	        return position;
+	    }
+	
+	    private Rect DrawPropertys(Rect position, SerializedProperty property)
+	    {
+	        Rect contentPosition = position;
+	        contentPosition.height = LineHeight;
+	        contentPosition = EditorGUI.PrefixLabel(contentPosition, new GUIContent(property.displayName));
+	        EditorGUI.PropertyField(contentPosition, property, GUIContent.none, true);
+	        if (property.isExpanded)
+	        {
+	            position.y += (LineHeight + LineSpan) * (property.arraySize + 2);
+                position.y += (LineHeight + LineSpan) * (2 * property.arraySize); //todo
+            }
+	        else
+	        {
+	            position.y += LineHeight + LineSpan;
+	        }
+	        return position;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Editor/AssetBundleGroupDrawer.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0a20806c95d59994cacdbff17024a24a
+timeCreated: 1512630292
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 61 - 0
Assets/Script/AssetBundleUtility/Editor/AssetBundleUtilityWindow.cs

@@ -0,0 +1,61 @@
+namespace assetBundleUtility
+{
+
+
+	using System;
+
+	using UnityEditor;
+	using UnityEngine;
+
+	public class AssetBundleUtilityWindow : EditorWindow
+	{
+	    #region Config
+	
+	    protected Vector2 ScrollPosition;
+	    protected GUIStyle TitleGUIStyle;
+	
+	    protected AssetBundleUtility Instance;
+	    protected SerializedObject SerializedObject;
+        protected SerializedProperty AssetBundleGroups;
+
+        #endregion
+
+        [MenuItem("DashGame/AssetBundleUtility")]
+	    protected static void ShowWindow()
+	    {
+	        Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll");
+	        AssetBundleUtilityWindow window = GetWindow<AssetBundleUtilityWindow>(inspectorType);
+	        window.titleContent = new GUIContent("AssetBundleUtility");
+            window.Show();
+	    }
+	
+	    private void OnEnable()
+	    {
+	        Instance = InstanceManager.SearchInstance<AssetBundleUtility>();
+	        SerializedObject = new SerializedObject(Instance);
+	        AssetBundleGroups = SerializedObject.FindProperty("AssetBundleGroups");
+	        TitleGUIStyle = new GUIStyle
+	        {
+	            fontSize = 20,
+	            alignment = TextAnchor.MiddleCenter,
+	            normal = { textColor = new Color(0.75f, 0.75f, 0.75f, 1) }
+	        };
+	    }
+	
+	    private void OnGUI()
+	    {
+	        SerializedObject.Update();
+	
+	        ScrollPosition = EditorGUILayout.BeginScrollView(ScrollPosition);
+	
+	        EditorGUILayout.LabelField("AssetBundleUtility", TitleGUIStyle, GUILayout.Height(30));
+	        EditorGUILayout.PropertyField(AssetBundleGroups, new GUIContent(AssetBundleGroups.displayName), true);
+	
+	        EditorGUILayout.EndScrollView();
+	
+	        SerializedObject.ApplyModifiedProperties();
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Editor/AssetBundleUtilityWindow.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b09ac0528d6c7984bb431e7c904a1a73
+timeCreated: 1512029836
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 37 - 0
Assets/Script/AssetBundleUtility/Editor/InstanceManager.cs

@@ -0,0 +1,37 @@
+namespace assetBundleUtility
+{
+    
+
+    using System.Collections.Generic;
+
+    using UnityEngine;
+    using UnityEditor;
+
+    using System;
+    using System.IO;
+
+    public class InstanceManager
+    {
+        public static T SearchInstance<T>()
+        {
+            foreach (var path in Directory.GetFiles(Application.dataPath, "AssetBundleUtility.prefab", SearchOption.AllDirectories))
+            {
+                T t = AssetDatabase.LoadAssetAtPath<GameObject>(path.GetRelativePath()).GetComponent<T>();
+
+                if (t != null)
+                {
+                    return t;
+                }
+            }
+
+            throw new Exception("找不到SerializeObject");
+        }
+
+        public static string[] SearchAllFiles(string pattern)
+        {
+            return Directory.GetFiles(Application.dataPath, pattern, SearchOption.AllDirectories);
+        }
+    }
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Editor/InstanceManager.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fd2192036ef190d47833916ff594b257
+timeCreated: 1512029836
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 97 - 0
Assets/Script/AssetBundleUtility/Editor/InstanceUtility.cs

@@ -0,0 +1,97 @@
+namespace assetBundleUtility
+{
+
+
+	using UnityEditor;
+
+	using System;
+	using System.Linq;
+	using System.Reflection;
+	using System.Collections;
+	using System.Collections.Generic;
+	
+	public class InstanceUtility
+	{
+	    private class RelativeObject
+	    {
+	        public int EnumerableIndex;
+	        public bool IsEnumerable;
+	        public string FieldName;
+	
+	        public RelativeObject(string fieldName, string enumerableIndex = null)
+	        {
+	            FieldName = fieldName;
+	
+	            if (enumerableIndex == null)
+	            {
+	                IsEnumerable = false;
+	            }
+	            else
+	            {
+	                EnumerableIndex = int.Parse(enumerableIndex.Substring(5, 1));
+	                IsEnumerable = true;
+	            }
+	        }
+	
+	        public object GetObject(object originObject)
+	        {
+	            object relativeObject = originObject.GetType().GetField(FieldName).GetValue(originObject);
+	
+	            if (IsEnumerable)
+	            {
+	                int index = 0;
+	                
+	                foreach (var obj in relativeObject as IEnumerable)
+	                {
+	                    if (index == EnumerableIndex)
+	                        return obj;
+	                    else
+	                        index++;
+	                }
+	            }
+	            else
+	            {
+	                return relativeObject;
+	            }
+	
+	            throw new Exception($"{FieldName} {IsEnumerable} {EnumerableIndex}");
+	        }
+	    }
+	
+	    public static object GetObject(FieldInfo fieldInfo, SerializedProperty property)
+	    {
+	        List<string> infos = property.propertyPath.Split('.').ToList();
+	
+	        List<RelativeObject> relativeObjects = new List<RelativeObject>();
+	
+	        for (int i = 0; i < infos.Count; i++)
+	        {
+	            if (i < infos.Count - 1 && infos[i + 1] == "Array")
+	            {
+	                relativeObjects.Add(new RelativeObject(infos[i], infos[i + 2]));
+	                i += 2;
+	            }
+	            else
+	            {
+	                relativeObjects.Add(new RelativeObject(infos[i]));
+	            }
+	        }
+	
+	        object obj = property.serializedObject.targetObject;
+	
+	        foreach (var relativeObject in relativeObjects)
+	        {
+	            obj = relativeObject.GetObject(obj);
+	        }
+	
+	        return obj;
+	    }
+	
+	    public static T GetPropertyDrawerInstance<T>(FieldInfo fieldInfo, SerializedProperty property) where T : class
+	    {
+	        return GetObject(fieldInfo, property) as T;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Editor/InstanceUtility.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a488d2b792d89a447b043e32e95cf875
+timeCreated: 1512630448
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Script/AssetBundleUtility/Extensions.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 518bf4c17c2fdef42a97c477d9dc0103
+folderAsset: yes
+timeCreated: 1512622594
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 275 - 0
Assets/Script/AssetBundleUtility/Extensions/ListExtension.cs

@@ -0,0 +1,275 @@
+namespace assetBundleUtility
+{
+
+
+	using UnityEngine;
+	using UnityEngine.Events;
+	
+	using System;
+	using System.Collections;
+	using System.Collections.Generic;
+	using System.Linq;
+	
+	public static class ListExtension
+	{
+	    public static T Roll<T>(this List<T> list)
+	    {
+	        T t = list[0];
+	        list.RemoveAt(0);
+	        list.Add(t);
+	        return list[0];
+	    }
+	
+	    public static void Switch<T>(this List<T> list, int index0, int index1)
+	    {
+	        T t0 = list[index0];
+	        list[index0] = list[index1];
+	        list[index1] = t0;
+	    }
+	
+	
+	    public static T Prev<T>(this List<T> list, int index)
+	    {
+	        return list[(index + list.Count - 1) % list.Count];
+	    }
+	
+	    public static T Next<T>(this List<T> list, int index)
+	    {
+	        return list[(index + 1) % list.Count];
+	    }
+	
+	
+	    public static T Back<T>(this List<T> list, int index, bool remove = false)
+	    {
+	        T t = list[list.Count - 1 - index];
+	
+	        if (remove)
+	        {
+	            list.RemoveAt(list.Count - 1 - index);
+	        }
+	
+	        return t;
+	    }
+	
+	    public static T Forward<T>(this List<T> list, int index, bool remove = false)
+	    {
+	        T t = list[index];
+	
+	        if (remove)
+	        {
+	            list.RemoveAt(index);
+	        }
+	
+	        return t;
+	    }
+	
+	    public static List<T> Random<T>(this List<T> list, int amt = 1, bool allDifferent = true, bool remove = false, Func<T,bool> func = null)
+	    {
+	        if (amt > list.Count && allDifferent)
+	        {
+	            throw new Exception();
+	        }
+	
+	
+	        int antiCrush = 0;
+	
+	        List<T> resultList = new List<T>();
+	
+	        while (resultList.Count < amt)
+	        {
+	            if (antiCrush++ > 10000)
+	            {
+	                throw new Exception();
+	            }
+	
+	            int index = UnityEngine.Random.Range(0, list.Count);
+	            
+	            T result = list[index];
+	
+	            if (func != null)
+	            {
+	                if (!func(result))
+	                {
+	                    continue;
+	                }
+	            }
+	
+	            if (allDifferent)
+	            {
+	                if (resultList.Contains(result))
+	                {
+	                    continue;
+	                }
+	            }
+	
+	            if (remove)
+	            {
+	                list.RemoveAt(index);
+	
+	                resultList.Add(result);
+	            }
+	            else
+	            {
+	                resultList.Add(result);
+	            }
+	        }
+	
+	        return resultList;
+	    }
+	
+	    public static List<T> Disturb<T>(this List<T> list)
+	    {
+	        List<T> resultList = new List<T>();
+	
+	        resultList.AddRange(list.Random(list.Count));
+	
+	        return resultList;
+	    }
+	
+	    public static List<T2> ToSingleList<T1,T2>(this List<T1> twoLevelList) where T1 : List<T2>
+	    {
+	        //for (int i = 0; i < highLevelList.Count; i++)
+	        //{
+	        //    highLevelList[i][i].GetType()
+	        //}
+	
+	        return null;
+	    }
+	
+	
+	    public static bool Valid<T>(this List<T> list)
+	    {
+	        if (list == null || list.Count == 0)
+	        {
+	            return false;
+	        }
+	        else
+	        {
+	            return true;
+	        }
+	    }
+	
+	    public static bool UniqueAdd<T>(this List<T> list, T obj)
+	    {
+	        if (list.Contains(obj) == false)
+	        {
+	            list.Add(obj);
+	
+	            return true;
+	        }
+	        else
+	        {
+	            return false;
+	        }
+	    }
+	
+	
+	    public static void ForEach<T>(this List<T> list, Action<T> action, bool remove = false)
+	    {
+	        for (int i = 0; i < list.Count; i++)
+	        {
+	            action(list[i]);
+	
+	            if (remove)
+	            {
+	                list.RemoveAt(i--);
+	            }
+	        }
+	    }
+	
+	    public static void BackRemoveAt<T>(this List<T> list, int index)
+	    {
+	        list.RemoveAt(list.Count - 1 - index);
+	    }
+	
+	
+	    public static void MySort<T>(this List<T> list, Func<T, T, bool> func)
+	    {
+	        bool finish = false;
+	
+	        for (int i = 0; i < list.Count; i++)
+	        {
+	            finish = true;
+	
+	            for (int j = 0; j < list.Count - i - 1; j++)
+	            {
+	                if (func(list[j], list[j + 1]))
+	                {
+	                    finish = false;
+	
+	                    T t = list[j];
+	
+	                    list[j] = list[j + 1];
+	                    list[j + 1] = t;
+	                }
+	            }
+	
+	            if (finish)
+	            {
+	                break;
+	            }
+	        }
+	    }
+	
+	    public static float MyMin<T>(this List<T> list, Func<T, float> func)
+	    {
+	        float result = func(list[0]);
+	
+	        for (int i = 1; i < list.Count; i++)
+	        {
+	            if (result > func(list[i]))
+	            {
+	                result = func(list[i]);
+	            }
+	        }
+	
+	        return result;
+	    }
+	
+	    public static float MyMax<T>(this List<T> list, Func<T, float> func)
+	    {
+	        float result = func(list[0]);
+	
+	        for (int i = 1; i < list.Count; i++)
+	        {
+	            if (result < func(list[i]))
+	            {
+	                result = func(list[i]);
+	            }
+	        }
+	
+	        return result;
+	    }
+	
+	    public static float MySum<T>(this List<T> list, Func<T,float> func, int count = -1)
+	    {
+	        if (count == -1)
+	        {
+	            count = list.Count;
+	        }
+	
+	        float result = 0;
+	        
+	        for (int i = 0; i < count; i++)
+	        {
+	            result += func(list[i]);
+	        }
+	
+	        return result;
+	    }
+	
+	    public static bool MyContains<T>(this List<T> list, Func<T, bool> func)
+	    {
+	        for (int i = 0; i < list.Count; i++)
+	        {
+	            if (func.Invoke(list[i]))
+	            {
+	                return true;
+	            }
+	        }
+	        return false;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Extensions/ListExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e77ba327d6d643142a801a0bf3b4e9a2
+timeCreated: 1512960178
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 54 - 0
Assets/Script/AssetBundleUtility/Extensions/PathExtension.cs

@@ -0,0 +1,54 @@
+namespace assetBundleUtility
+{
+
+
+	using System.Collections.Generic;
+	using System.IO;
+	
+	using UnityEngine;
+	
+	public static class PathExtension
+	{
+	    public static string GetRelativePath(this string path)
+	    {
+	        return "Assets" + path.Replace(Application.dataPath, "");
+	    }
+	
+	    public static List<string> GetAllFileNameFromPath(this List<string> pathes)
+	    {
+	        List<string> fileName = new List<string>();
+	        foreach (var path in pathes)
+	        {
+	            fileName.Add(Path.GetFileName(path));
+	        }
+	        return fileName;
+	    }
+	
+	    public static string GetUnRepeatFileName(this string fileName)
+	    {
+	        string extension = Path.GetExtension(fileName);
+	        string directory = Path.GetDirectoryName(fileName);
+	        string name = Path.GetFileNameWithoutExtension(fileName);
+	        int count = 1;
+	        string newFileName = $"{directory}{Path.DirectorySeparatorChar}{name}{extension}";
+	        while (File.Exists(newFileName))
+	        {
+	            newFileName = $"{directory}{Path.DirectorySeparatorChar}{name} ({count++}){extension}";
+	        }
+	        return newFileName;
+	    }
+	
+	    public static string GetUnRepeatDirectoryName(this string directoryName)
+	    {
+	        int count = 1;
+	        string newDirectoryName = directoryName;
+	        while (Directory.Exists(newDirectoryName))
+	        {
+	            newDirectoryName = $"{directoryName} ({count++})";
+	        }
+	        return newDirectoryName;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Extensions/PathExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: af306594be989f84a9239456180f9e18
+timeCreated: 1512029854
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 41 - 0
Assets/Script/AssetBundleUtility/Extensions/SortExtension.cs

@@ -0,0 +1,41 @@
+namespace assetBundleUtility
+{
+
+
+	using System;
+	using System.Collections;
+	using System.Collections.Generic;
+	
+	using UnityEngine;
+	
+	public static class SortExtension
+	{
+        /// <summary>
+        /// str0µÄASCIIÊÇ·ñ±Èstr1µÄASCIIС
+        /// </summary>
+        /// <param name="str0"></param>
+        /// <param name="str1"></param>
+        /// <returns></returns>
+	    public static bool CompareASCII(string str0, string str1)
+	    {
+	        for (int i = 0; i < str0.Length; i++)
+	        {
+	            if (i >= str1.Length)
+	            {
+	                return true;
+	            }
+	            else if (str0[i] < str1[i])
+	            {
+	                return true;
+	            }
+	            else if (str0[i] > str1[i])
+	            {
+	                return false;
+	            }
+	        }
+	        throw new Exception();
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Extensions/SortExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 56f11b2dd0731dd4a86fb8136791fe49
+timeCreated: 1512960591
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 24 - 0
Assets/Script/AssetBundleUtility/Extensions/StringExtension.cs

@@ -0,0 +1,24 @@
+namespace assetBundleUtility
+{
+
+
+	using System.Collections;
+	using System.Collections.Generic;
+	
+	using UnityEngine;
+	
+	public static class StringExtension
+	{
+	    public static List<string> ReplaceAll(this List<string> strings, string oldValue, string newValue)
+	    {
+	        List<string> results = new List<string>();
+	        for (int i = 0; i < strings.Count; i++)
+	        {
+	            results.Add(strings[i].Replace(oldValue, newValue));
+	        }
+	        return results;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/Extensions/StringExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e8b3a338e8b3b86468565eb3f070e2d5
+timeCreated: 1512624240
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Assets/Script/AssetBundleUtility/MD5Utility.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 48ea437c003de404e9843c723c777e6e
+folderAsset: yes
+timeCreated: 1512622541
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 59 - 0
Assets/Script/AssetBundleUtility/MD5Utility/MD5Utility.cs

@@ -0,0 +1,59 @@
+namespace assetBundleUtility
+{
+
+
+	using System.Collections.Generic;
+	using System.IO;
+	using System.Security.Cryptography;
+	using System.Text;
+	
+	public class MD5Utility
+	{
+	    public static byte[] GetMD5(string str)
+	    {
+	        byte[] bytes = Encoding.UTF8.GetBytes(str);
+	        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
+	        byte[] md5Bytes = md5.ComputeHash(bytes);
+	        return md5Bytes;
+	    }
+	
+	    public static byte[] GetMD5(FileStream fileStream)
+	    {
+	        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
+	        byte[] md5Bytes = md5.ComputeHash(fileStream);
+	        return md5Bytes;
+	    }
+	
+	    public static string BytesToString(byte[] bytes)
+	    {
+	        StringBuilder stringBuilder = new StringBuilder();
+	        foreach (var md5Byte in bytes)
+	        {
+	            stringBuilder.Append(md5Byte.ToString("X2")); //X2表示转为大写
+	        }
+	        return stringBuilder.ToString();
+	    }
+	
+	    public static List<string> GetAllMD5StringFromPath(List<string> pathes)
+	    {
+	        List<string> md5Strings = new List<string>();
+	        for (int i = 0; i < pathes.Count; i++)
+	        {
+	            string md5String = GetMD5StringFromPath(pathes[i]);
+	            md5Strings.Add(md5String);
+	        }
+	        return md5Strings;
+	    }
+	
+	    public static string GetMD5StringFromPath(string path)
+	    {
+	        FileStream fileStream = new FileStream(path, FileMode.Open);
+	        byte[] bytes = GetMD5(fileStream);
+	        string md5Strings = BytesToString(bytes);
+	        fileStream.Close();
+	        return md5Strings;
+	    }
+	}
+
+
+}

+ 12 - 0
Assets/Script/AssetBundleUtility/MD5Utility/MD5Utility.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 26e8cf55ab749074495d7dea4cd99480
+timeCreated: 1512622610
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 2 - 0
Assets/Script/Editor/EditorBundle.cs

@@ -172,6 +172,8 @@ public class EditorBundle : Editor
             "new_dress_ske",
             "new_dress_config",
             "new_language_config",
+            "new_flower_config",
+            "new_flower_tex",
         };
         foreach (var name in names)
         {

+ 11 - 1
Assets/Script/Label/ResourceLabel.cs

@@ -5,7 +5,13 @@ using UnityEngine;
 
 public class ResourceLabel
 {
-    
+    public static string NewDressConfig = "new_dress_config";
+    public static string NewDressSke = "new_dress_ske";
+    public static string NewDressTex = "new_dress_tex";
+    public static string NewLanguage = "new_language_config";
+    public static string NewFlowerConfig = "new_flower_config";
+    public static string NewFlowerTex = "new_flower_tex";
+
     public static string ChestTimer = "ChestTimer";
     public static string PlazaRoom = "PlazaRoom";
     public static string ObjPool = "ObjPool";
@@ -113,6 +119,10 @@ public class ResourceLabel
     public static string OfflineConfig = "offline_config";
     public static string PlayerConfig= "PlayerConfig";
     public static string PlayerConfigXml = "PlayerConfig.xml";
+    public static string NewDressroomConfig = "new_dressRoom_config";
+    public static string NewEnglish = "new_English";
+    public static string NewChineseSimplified = "new_ChineseSimplified";
+    public static string NewChineseTraditional = "new_ChineseTraditional";
 
     public static string BtnClip = "BtnClip";
     public static string SkillClip = "SkillClip";

+ 10 - 8
Assets/Script/Manage/ConfigManager.cs

@@ -1124,16 +1124,17 @@ public class ConfigManager : Regist
         return attributeList;
     }
 
-    public static List<XmlAttributeCollection> GetFlowerConfig()
+    public static List<XmlAttributeCollection> GetFlowerConfig(TextAsset textAsset = null)
     {
-        TextAsset textAsset;
         XmlNodeList xmlNodeList;
 
         XmlDocument xmlDoc = new XmlDocument();
         List<XmlAttributeCollection> attributeList = new List<XmlAttributeCollection>();
-        
 
-        textAsset = ResourceManager.Load<TextAsset>(ResourceLabel.FlowerConfig, Folder.Config);
+        if (textAsset == null)
+        {
+            textAsset = ResourceManager.Load<TextAsset>(ResourceLabel.FlowerConfig, Folder.Config);
+        }
 
         xmlDoc.LoadXml(textAsset.text);
 
@@ -1193,16 +1194,17 @@ public class ConfigManager : Regist
         return attributeList;
     }
 
-    public static List<XmlAttributeCollection> GetDressRoomConfig()
+    public static List<XmlAttributeCollection> GetDressRoomConfig(TextAsset textAsset = null)
     {
-        TextAsset textAsset;
         XmlNodeList xmlNodeList;
 
         XmlDocument xmlDoc = new XmlDocument();
         List<XmlAttributeCollection> attributeList = new List<XmlAttributeCollection>();
 
-
-        textAsset = ResourceManager.Load<TextAsset>(ResourceLabel.DressroomConfig, Folder.Config);
+        if (textAsset == null)
+        {
+            textAsset = ResourceManager.Load<TextAsset>(ResourceLabel.DressroomConfig, Folder.Config);
+        }
 
         xmlDoc.LoadXml(textAsset.text);
 

+ 1 - 1
Assets/Script/Manage/GardenManager.cs

@@ -343,7 +343,7 @@ public class GardenManager : Regist
         #region 生成FlowerItem
 
         List<XmlAttributeCollection> attributeList = ConfigManager.GetFlowerConfig();
-
+        attributeList.AddRange(Bundle.NewFlowerConfigs);
         for (int i = 0; i < attributeList.Count; i++)
         {
             FlowerInfo flowerInfo = new FlowerInfo(attributeList[i]);

+ 8 - 3
Assets/Script/Manage/Initializer.cs

@@ -247,8 +247,6 @@ public class Initializer : MonoBehaviour
 
     public static void InstantiatePrefabs()
     {
-        DebugText = GameObject.Find(CanvasLabel.U_DebugLab).GetComponent<Text>();
-
         DebugText.text = "Error code : 1";
 
         TutorialManager.NewplayerTutorial = ConfigManager.GetBoolFormConfig(PlayerConfigLabel.NewplayerTutorial);
@@ -404,6 +402,14 @@ public class Initializer : MonoBehaviour
             yield return null;
         }
 
+        DebugText = GameObject.Find(CanvasLabel.U_DebugLab).GetComponent<Text>();
+        Bundle.UpdateAssetBundle();
+
+        while (!Bundle.UpdateComplete)
+        {
+            yield return null;
+        }
+
         while (ConfigManager.PlayerDocumentDamageFlag)
         {
             yield return null;
@@ -412,7 +418,6 @@ public class Initializer : MonoBehaviour
         Language.Initialize();
         UIManager.Init(Instance.DebugMode);
         AudioManager.Init();
-
         InitEntrance();
     }
 

+ 140 - 0
Assets/Script/Tool/Bundle.cs

@@ -5,7 +5,9 @@ using UnityEngine.Events;
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Xml;
+using assetBundleUtility;
 using DragonBones;
 #if UNITY_EDITOR
 using UnityEditor;
@@ -18,7 +20,15 @@ public class Bundle : MonoBehaviour
 {
     #region
 
+    public static bool UpdateComplete;
+    public static AssetBundle NewDressConfig;
+    public static AssetBundle NewDressSke;
+    public static AssetBundle NewDressTex;
+    public static AssetBundle NewLanguage;
+    public static AssetBundle NewFlowerConfig;
+    public static AssetBundle NewFlowerTex;
     public static List<XmlAttributeCollection> NewDressroomConfigs = new List<XmlAttributeCollection>();
+    public static List<XmlAttributeCollection> NewFlowerConfigs = new List<XmlAttributeCollection>();
 
 
     public static Bundle Instance;
@@ -640,4 +650,134 @@ public class Bundle : MonoBehaviour
             Debug.Log(www.error);
         }
     }
+
+
+    public static void UpdateAssetBundle()
+    {
+        string persistentFolder = $"{Application.persistentDataPath}{Path.DirectorySeparatorChar}HotUpdate";
+        string streamingFolder = $"{Application.streamingAssetsPath}{Path.DirectorySeparatorChar}Bundle{Path.DirectorySeparatorChar}Windows{Path.DirectorySeparatorChar}HotUpdate";
+        List<AssetBundleSet> assetBundleSets = AssetBundleUtility.GetAssetBundleSetsFromFolders
+        (
+            persistentFolder,
+            streamingFolder
+        );
+        string localMD5 = AssetBundleUtility.GetMD5OfAssetBundleSets(assetBundleSets);
+        string serverMD5 = "AE29F7EE00843A792D96CA02D6907FAA";
+        //bool needUpdate = localMD5 != serverMD5;
+        bool needUpdate = false;
+        Debug.LogWarning($"NeedUpdate : {needUpdate}");
+        if (needUpdate)
+        {
+            AssetBundleUtility.UpdateAllAssetBundle
+            (
+                "new_dress_config|F1F0FA4EB0C70A658BB03E935738C422|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_dress_config\r\nnew_dress_ske|531AE05FA301BBAD7B58B532BCD04CFD|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_dress_ske\r\nnew_dress_tex|3060DC78E5C9A8D58CF440C6C66035C4|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_dress_tex\r\nnew_flower_config|0CD417F29E1C7580A742BFC33DAE7DF5|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_flower_config\r\nnew_flower_tex|8640D886CB7D71B5D5EBA8D0FF037573|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_flower_tex\r\nnew_language_config|D7683A0A8867FBC6D32CFF5C9F41BAC4|file://E:\\UnityProject\\Garden5\\Assets\\HotUpdateTest\\new_language_config",
+                persistentFolder,
+                assetBundleSets,
+                DownloadAllAssetBundleSucceed,
+                DownloadAllAssetBundleFailed,
+                DownloadAssetBundleSucceed,
+                DownloadAssetBundleFailed
+            );
+        }
+        else
+        {
+            AssetBundleUtility.LoadAllAssetBundle
+            (
+                assetBundleSets,
+                DownloadAllAssetBundleSucceed,
+                DownloadAllAssetBundleFailed,
+                DownloadAssetBundleSucceed,
+                DownloadAssetBundleFailed
+            );
+        }
+    }
+
+    public static void DownloadAllAssetBundleSucceed()
+    {
+        NewDressroomConfigs = ConfigManager.GetDressRoomConfig(NewDressConfig.LoadAsset<TextAsset>(ResourceLabel.NewDressroomConfig));
+
+        TextAsset[] textAssets = NewDressSke.LoadAllAssets<TextAsset>();
+        foreach (var textAsset in textAssets)
+        {
+            UnityFactory.factory.LoadDragonBonesData(textAsset);
+        }
+
+        textAssets = NewDressTex.LoadAllAssets<TextAsset>();
+        Texture2D[] textures = NewDressTex.LoadAllAssets<Texture2D>();
+        for (int i = 0; i < textAssets.Length; i++)
+        {
+            ResourceManager.ObjectDictionary.Add(textures[i].name, textures[i]);
+            UnityFactory.factory.LoadTextureAtlasData(textAssets[i], textures[i].name);
+        }
+
+        Sprite[] sprites = NewDressTex.LoadAllAssets<Sprite>();
+        for (int i = 0; i < sprites.Length; i++)
+        {
+            PlayerManager.CloseSpriteDictionary.Add(sprites[i].name, sprites[i]);
+            ResourceManager.ObjectDictionary.UniqueAdd(sprites[i].name, sprites[i]);
+        }
+
+        TextAsset language = NewLanguage.LoadAsset<TextAsset>(ResourceLabel.NewEnglish);
+        XmlDocument document = new XmlDocument();
+        document.LoadXml(language.text);
+        Language.AddLanguageDocument(CurrentLanguage.English, document);
+
+        language = NewLanguage.LoadAsset<TextAsset>(ResourceLabel.NewChineseSimplified);
+        document = new XmlDocument();
+        document.LoadXml(language.text);
+        Language.AddLanguageDocument(CurrentLanguage.ChineseSimplified, document);
+
+        language = NewLanguage.LoadAsset<TextAsset>(ResourceLabel.NewChineseTraditional);
+        document = new XmlDocument();
+        document.LoadXml(language.text);
+        Language.AddLanguageDocument(CurrentLanguage.ChineseTraditional, document);
+
+        NewFlowerConfigs = ConfigManager.GetFlowerConfig(NewFlowerConfig.LoadAsset<TextAsset>(ResourceLabel.NewFlowerConfig));
+
+        sprites = NewFlowerTex.LoadAllAssets<Sprite>();
+        for (int i = 0; i < sprites.Length; i++)
+        {
+            ResourceManager.ObjectDictionary.UniqueAdd(sprites[i].name, sprites[i]);
+        }
+
+        UpdateComplete = true;
+    }
+
+    public static void DownloadAllAssetBundleFailed()
+    {
+        Debug.Log("failed");
+    }
+
+    public static void DownloadAssetBundleSucceed(AssetBundleSet assetBundleSet)
+    {
+        if (assetBundleSet.Name == ResourceLabel.NewDressConfig)
+        {
+            NewDressConfig = assetBundleSet.AssetBundle;
+        }
+        else if (assetBundleSet.Name == ResourceLabel.NewDressSke)
+        {
+            NewDressSke = assetBundleSet.AssetBundle;
+        }
+        else if (assetBundleSet.Name == ResourceLabel.NewDressTex)
+        {
+            NewDressTex = assetBundleSet.AssetBundle;
+        }
+        else if (assetBundleSet.Name == ResourceLabel.NewLanguage)
+        {
+            NewLanguage = assetBundleSet.AssetBundle;
+        }
+        else if (assetBundleSet.Name == ResourceLabel.NewFlowerConfig)
+        {
+            NewFlowerConfig = assetBundleSet.AssetBundle;
+        }
+        else if (assetBundleSet.Name == ResourceLabel.NewFlowerTex)
+        {
+            NewFlowerTex = assetBundleSet.AssetBundle;
+        }
+    }
+
+    public static void DownloadAssetBundleFailed(AssetBundleSet assetBundleSet, string error)
+    {
+        Debug.Log(error);
+    }
 }

+ 0 - 3
第五期.txt

@@ -9,9 +9,6 @@
 回档的问题
 
 
-热更新要考虑到花朵配置 服装配置 语言配置 龙骨
-
-
 //关闭DebugMode 开启CatchException
 
 //切换到远程服务器 正常Zone