├── .gitignore ├── Assets ├── Sample.meta ├── Sample │ ├── Editor.meta │ ├── Editor │ │ ├── AssetBundleSampleDataWindow.cs │ │ └── AssetBundleSampleDataWindow.cs.meta │ ├── origin.png │ └── origin.png.meta ├── SeparatedAssetBundleBuild.meta └── SeparatedAssetBundleBuild │ ├── Editor.meta │ └── Editor │ ├── AllAssetBundleInformation.cs │ ├── AllAssetBundleInformation.cs.meta │ ├── AssetBundleBuildsManifest.cs │ ├── AssetBundleBuildsManifest.cs.meta │ ├── AssetBundleInfoWithDepends.cs │ ├── AssetBundleInfoWithDepends.cs.meta │ ├── SeparatedAssetBundleBuild.cs │ └── SeparatedAssetBundleBuild.cs.meta ├── LICENSE ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityAdsSettings.asset └── UnityConnectSettings.asset ├── README.ja.md ├── README.md ├── SeparatedAssetBundleBuild.unitypackage └── doc └── img ├── AssetBundleBuildTime.png ├── SampleWindow.png └── WorkAroundBuildTime.png /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | *.unitypackage 31 | -------------------------------------------------------------------------------- /Assets/Sample.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb91e0eb753de5944b54c03a3489b268 3 | folderAsset: yes 4 | timeCreated: 1487232909 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Sample/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f66bd6180e2cb07478f844c93f2913a4 3 | folderAsset: yes 4 | timeCreated: 1487061549 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Sample/Editor/AssetBundleSampleDataWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.IO; 5 | using System.Collections.Generic; 6 | 7 | namespace Sample 8 | { 9 | public class AssetBundleSampleDataWindow : EditorWindow 10 | { 11 | private const string outputDir = "Test"; 12 | private int testDataNum = 1000; 13 | private List testVariants = new List(); 14 | 15 | [MenuItem("Samples/SampleWindow")] 16 | public static void Create() 17 | { 18 | EditorWindow.GetWindow(); 19 | } 20 | 21 | void OnGUI() 22 | { 23 | EditorGUILayout.LabelField("Create Test Data"); 24 | this.testDataNum = EditorGUILayout.IntField("Number of testdata",this.testDataNum); 25 | int newCount = Mathf.Max(0, EditorGUILayout.IntField("Number of variants", this.testVariants.Count)); 26 | while (newCount < this.testVariants.Count) 27 | this.testVariants.RemoveAt(this.testVariants.Count - 1); 28 | while (newCount > this.testVariants.Count) 29 | this.testVariants.Add(null); 30 | for(int i = 0; i < this.testVariants.Count; i++) 31 | { 32 | this.testVariants[i] = EditorGUILayout.TextField(this.testVariants[i]); 33 | } 34 | 35 | if (GUILayout.Button("CreateTestData")) 36 | { 37 | if (this.testVariants.Count > 0) 38 | { 39 | this.CreateDatasetWithVariants(this.testDataNum, this.testVariants.ToArray()); 40 | } 41 | else 42 | { 43 | this.CreateDataset(this.testDataNum); 44 | } 45 | } 46 | 47 | EditorGUILayout.Space(); 48 | EditorGUILayout.LabelField("BuildAssetBundles"); 49 | if (GUILayout.Button("BuildPipeline.BuildAssetBundles")) 50 | { 51 | BuildBundle(false); 52 | } 53 | if (GUILayout.Button(" UTJ.SeparateAssetBundleBuild.BuildAssetBundles")) 54 | { 55 | BuildBundle(true); 56 | } 57 | } 58 | 59 | private void BuildBundle(bool isSeparate) 60 | { 61 | BuildAssetBundleOptions assetBundleBuildOption = BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.ForceRebuildAssetBundle; 62 | BuildTarget targetPlatform = EditorUserBuildSettings.activeBuildTarget; 63 | 64 | if (Directory.Exists(outputDir)) 65 | { 66 | Directory.Delete(outputDir, true); 67 | } 68 | Directory.CreateDirectory(outputDir); 69 | 70 | float beforeAssetBundle = Time.realtimeSinceStartup; 71 | 72 | if (isSeparate) 73 | { 74 | UTJ.SeparatedAssetBundleBuild.ReservedVariants = testVariants; 75 | UTJ.SeparatedAssetBundleBuild.BuildAssetBundles(outputDir, assetBundleBuildOption, targetPlatform); 76 | } 77 | else 78 | { 79 | BuildPipeline.BuildAssetBundles(outputDir, assetBundleBuildOption, targetPlatform); 80 | } 81 | float afterAssetBundle = Time.realtimeSinceStartup; 82 | 83 | UnityEngine.Debug.Log("BuildAssetBundle " + (afterAssetBundle - beforeAssetBundle)); 84 | string title = "UTJ.SeparatedAssetBundleBuild.BuildAssetBundles\n"; 85 | if (isSeparate) 86 | { 87 | title = "BuildPipeline.BuildAssetBundles \n"; 88 | } 89 | EditorUtility.DisplayDialog(title , "It took " + (afterAssetBundle - beforeAssetBundle) + " sec.", "ok"); 90 | } 91 | 92 | public void CreateDataset(int num) 93 | { 94 | string testDir = "Assets/Sample/TestBundles"; 95 | 96 | if (Directory.Exists(testDir)) 97 | { 98 | Directory.Delete(testDir, true); 99 | } 100 | Directory.CreateDirectory(testDir); 101 | 102 | CreateTestAsset(testDir, num); 103 | 104 | AssetDatabase.Refresh(); 105 | AssetDatabase.RemoveUnusedAssetBundleNames(); 106 | 107 | SetAssetBundleName(testDir, num); 108 | } 109 | 110 | public void CreateDatasetWithVariants(int num, string[] variants) 111 | { 112 | string testDir = "Assets/Sample/TestBundles"; 113 | 114 | if (Directory.Exists(testDir)) 115 | { 116 | Directory.Delete(testDir, true); 117 | } 118 | Directory.CreateDirectory(testDir); 119 | 120 | for (int i = 0; i < variants.Length; i++) 121 | { 122 | string targetDirectory = Path.Combine(testDir, variants[i]); 123 | Directory.CreateDirectory(targetDirectory); 124 | CreateTestAsset(targetDirectory, num); 125 | } 126 | 127 | AssetDatabase.Refresh(); 128 | AssetDatabase.RemoveUnusedAssetBundleNames(); 129 | 130 | for (int i = 0; i < variants.Length; i++) 131 | { 132 | string targetDir = Path.Combine(testDir, variants[i]); 133 | SetAssetBundleName(targetDir, num, variants[i]); 134 | } 135 | } 136 | 137 | private void CreateTestAsset(string targerDirectory, int num) 138 | { 139 | for (int i = 0; i < num; ++i) 140 | { 141 | string targetPath = Path.Combine(targerDirectory, i + ".png"); 142 | System.IO.File.Copy("Assets/Sample/origin.png", targetPath); 143 | } 144 | } 145 | 146 | private void SetAssetBundleName(string targerDirectory, int num, string variant = null) 147 | { 148 | for (int i = 0; i < num; ++i) 149 | { 150 | string targetPath = Path.Combine(targerDirectory, i + ".png"); 151 | TextureImporter importer = TextureImporter.GetAtPath(targetPath) as TextureImporter; 152 | if (importer == null) 153 | { 154 | continue; 155 | } 156 | importer.assetBundleName = "test" + i; 157 | importer.assetBundleVariant = variant; 158 | importer.textureType = TextureImporterType.GUI; 159 | importer.mipmapEnabled = false; 160 | } 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Assets/Sample/Editor/AssetBundleSampleDataWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd0671a0f7a7fa440959b6699cd406b7 3 | timeCreated: 1487061557 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/Sample/origin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/Assets/Sample/origin.png -------------------------------------------------------------------------------- /Assets/Sample/origin.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b4aa2d45754d15f4a930a88dc61586b1 3 | timeCreated: 1487062115 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: -1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 0 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 32 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 32 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: iPhone 70 | maxTextureSize: 32 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | - buildTarget: Android 78 | maxTextureSize: 32 79 | textureFormat: -1 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 0 85 | spriteSheet: 86 | serializedVersion: 2 87 | sprites: [] 88 | outline: [] 89 | spritePackingTag: 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 769c631cf2fcbca489f0e1c8d25ad509 3 | folderAsset: yes 4 | timeCreated: 1487233344 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42126647864a7364fbc14f5e9b86310b 3 | folderAsset: yes 4 | timeCreated: 1487234743 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AllAssetBundleInformation.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace UTJ 5 | { 6 | public class AllAssetBundleInformation 7 | { 8 | public List noDependList = new List(); 9 | public Dictionary> dependGroup = new Dictionary>(); 10 | } 11 | } -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AllAssetBundleInformation.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 543b08dfcd0af554bbf558695335dfc0 3 | timeCreated: 1487234859 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AssetBundleBuildsManifest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | 6 | namespace UTJ 7 | { 8 | /// 9 | /// AssetBundleManifest 10 | /// 11 | public class AssetBundleBuildsManifest 12 | { 13 | private List allAssetBundles = new List(); 14 | private Dictionary allDependencies = new Dictionary(); 15 | private Dictionary allHash = new Dictionary(); 16 | 17 | public string[] GetAllAssetBundles() 18 | { 19 | return allAssetBundles.ToArray(); 20 | } 21 | public string[] GetAllDependencies(string name) 22 | { 23 | string[] val = null; 24 | allDependencies.TryGetValue(name, out val); 25 | return val; 26 | } 27 | public Hash128 GetAssetBundleHash(string name) 28 | { 29 | Hash128 hash = new Hash128(); 30 | allHash.TryGetValue(name, out hash); 31 | return hash; 32 | } 33 | 34 | public void AddUnityManifest(UnityEngine.AssetBundleManifest manifest) 35 | { 36 | if (manifest == null) { return; } 37 | string[] inOriginList = manifest.GetAllAssetBundles(); 38 | foreach (var origin in inOriginList) 39 | { 40 | allAssetBundles.Add(origin); 41 | allDependencies.Add(origin, manifest.GetAllDependencies(origin)); 42 | allHash.Add(origin, manifest.GetAssetBundleHash(origin)); 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AssetBundleBuildsManifest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b8a1cab4da6e1745bb283b41748c3da 3 | timeCreated: 1487234737 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AssetBundleInfoWithDepends.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using UnityEngine; 4 | using UnityEditor; 5 | 6 | namespace UTJ 7 | { 8 | public class AssetBundleInfoWithDepends 9 | { 10 | public string assetBundleName { private set; get; } 11 | public HashSet dependsAssetBundleList; 12 | public HashSet useThisAssetBundleList; 13 | public int groupId = -1; 14 | public bool isNonDepend 15 | { 16 | get 17 | { 18 | return (dependsAssetBundleList == null) && (useThisAssetBundleList == null); 19 | } 20 | } 21 | 22 | public AssetBundleInfoWithDepends(string name) 23 | { 24 | this.assetBundleName = name; 25 | 26 | string[] depends = AssetDatabase.GetAssetBundleDependencies(this.assetBundleName, true); 27 | if (depends == null) 28 | { 29 | return; 30 | } 31 | foreach (var depend in depends) 32 | { 33 | AddList(depend, ref this.dependsAssetBundleList); 34 | } 35 | } 36 | public void AddUseThisAssetBundleList(string name) 37 | { 38 | AddList(name, ref this.useThisAssetBundleList); 39 | } 40 | 41 | private void AddList(string assetBundle, ref HashSet dataset) 42 | { 43 | if (string.IsNullOrEmpty(assetBundle)) 44 | { 45 | return; 46 | } 47 | if (dataset == null) 48 | { 49 | dataset = new HashSet(); 50 | } 51 | if (!dataset.Contains(assetBundle)) 52 | { 53 | dataset.Add(assetBundle); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/AssetBundleInfoWithDepends.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 98ebedca3d933c547b9e4122c63b3c8f 3 | timeCreated: 1487234781 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/SeparatedAssetBundleBuild.cs: -------------------------------------------------------------------------------- 1 | //#define ASSET_BUNDLE_GROUPING_DEBUG 2 | //#define ASSET_BUNDLE_BUILD_TIME_CHECK 3 | 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Text; 7 | using UnityEngine; 8 | using UnityEditor; 9 | 10 | 11 | 12 | namespace UTJ 13 | { 14 | /// 15 | /// call BuildPipeline.BuildAssetBundles separately. 16 | /// because of Unity5.5 regression. 17 | /// 18 | public class SeparatedAssetBundleBuild 19 | { 20 | 21 | // The number of batchingAssetBundleBuilds. 22 | private const int BulkConvertNum = 300; 23 | public static List ReservedVariants = new List(0); 24 | 25 | public static AssetBundleBuildsManifest BuildAssetBundles(string outputDir, BuildAssetBundleOptions buildOption, BuildTarget targetPlatform) 26 | { 27 | #if ASSET_BUNDLE_BUILD_TIME_CHECK 28 | float startTime = Time.realtimeSinceStartup; 29 | #endif 30 | 31 | AssetBundleBuildsManifest manifest = new AssetBundleBuildsManifest(); 32 | 33 | AssetBundleManifest unityManifest = null; 34 | // append 35 | AllAssetBundleInformation allAssetBundleInfo = GetAllAssetBundleInfoList(); 36 | int allAssetBundleCount = AssetDatabase.GetAllAssetBundleNames().Length; 37 | // 38 | List buildTargetBuffer = new List(); 39 | 40 | #if ASSET_BUNDLE_BUILD_TIME_CHECK 41 | float groupingComplete = Time.realtimeSinceStartup; 42 | #endif 43 | 44 | 45 | /// Build NoDependAssetBundles 46 | int idx = 0; 47 | foreach (var noDependAssetBundle in allAssetBundleInfo.noDependList) 48 | { 49 | string assetBundleName = noDependAssetBundle.assetBundleName; 50 | buildTargetBuffer.Add(CreateAssetBundleBuildFromAssetBundleName(assetBundleName)); 51 | if (buildTargetBuffer.Count > BulkConvertNum) 52 | { 53 | #if ASSET_BUNDLE_GROUPING_DEBUG 54 | DebugPrintBuildPipeline(buildTargetBuffer); 55 | #endif 56 | unityManifest = BuildPipeline.BuildAssetBundles(outputDir, buildTargetBuffer.ToArray(), buildOption, targetPlatform); 57 | manifest.AddUnityManifest(unityManifest); 58 | buildTargetBuffer.Clear(); 59 | } 60 | ++idx; 61 | EditorUtility.DisplayProgressBar("process no dependence bundles", assetBundleName, (float)idx / (float)allAssetBundleCount); 62 | } 63 | if (buildTargetBuffer.Count > 0) 64 | { 65 | #if ASSET_BUNDLE_GROUPING_DEBUG 66 | DebugPrintBuildPipeline(buildTargetBuffer); 67 | #endif 68 | unityManifest = BuildPipeline.BuildAssetBundles(outputDir, buildTargetBuffer.ToArray(), buildOption, targetPlatform); 69 | manifest.AddUnityManifest(unityManifest); 70 | buildTargetBuffer.Clear(); 71 | } 72 | 73 | // group set 74 | var dependGroupList = new List>(allAssetBundleInfo.dependGroup.Values); 75 | int length = dependGroupList.Count; 76 | 77 | for (int i = 0; i < length; ++i) 78 | { 79 | string assetBundleName = ""; 80 | foreach (var assetBundle in dependGroupList[i]) 81 | { 82 | assetBundleName = assetBundle.assetBundleName; 83 | buildTargetBuffer.Add(CreateAssetBundleBuildFromAssetBundleName(assetBundleName)); 84 | ++idx; 85 | } 86 | bool buildFlag = false; 87 | buildFlag |= (buildTargetBuffer.Count > BulkConvertNum); 88 | buildFlag |= (i == length - 1); 89 | if (i < length - 1) 90 | { 91 | buildFlag |= (dependGroupList[i + 1].Count > BulkConvertNum); 92 | } 93 | 94 | if (buildFlag) 95 | { 96 | #if ASSET_BUNDLE_GROUPING_DEBUG 97 | DebugPrintBuildPipeline(buildTargetBuffer); 98 | #endif 99 | unityManifest = BuildPipeline.BuildAssetBundles(outputDir, buildTargetBuffer.ToArray(), buildOption, targetPlatform); 100 | manifest.AddUnityManifest(unityManifest); 101 | buildTargetBuffer.Clear(); 102 | } 103 | EditorUtility.DisplayProgressBar("process dependence", "group " + i + " " + assetBundleName, (float)idx / (float)allAssetBundleCount); 104 | } 105 | EditorUtility.ClearProgressBar(); 106 | #if ASSET_BUNDLE_BUILD_TIME_CHECK 107 | float buildCompleteTime = Time.realtimeSinceStartup; 108 | 109 | UnityEngine.Debug.Log("All BuildTime:" + (buildCompleteTime - startTime) + "sec\n" + 110 | "GroupingTime:" + (groupingComplete - startTime) + "sec\n" + 111 | "AssetBundleBuild:" + (buildCompleteTime - groupingComplete) + "sec\n"); 112 | #endif 113 | return manifest; 114 | } 115 | #if ASSET_BUNDLE_GROUPING_DEBUG 116 | private static void DebugPrintBuildPipeline(List buildTargetBuffer) 117 | { 118 | StringBuilder sb = new StringBuilder(); 119 | sb.Append("BuildPipeline.BuildAssetBundles ").Append(buildTargetBuffer.Count).Append("\n"); 120 | foreach (var target in buildTargetBuffer) 121 | { 122 | sb.Append(target.assetBundleName).Append("\n"); 123 | } 124 | 125 | UnityEngine.Debug.Log(sb.ToString()); 126 | } 127 | #endif 128 | 129 | private static AllAssetBundleInformation GetAllAssetBundleInfoList() 130 | { 131 | AllAssetBundleInformation allAsssetBundleInfo = new AllAssetBundleInformation(); 132 | var assetBundleNames = AssetDatabase.GetAllAssetBundleNames(); 133 | 134 | Dictionary infoDictionary = new Dictionary(assetBundleNames.Length); 135 | // Check Depencencies 136 | int idx = 0; 137 | foreach (var assetBundleName in assetBundleNames) 138 | { 139 | infoDictionary.Add(assetBundleName, new AssetBundleInfoWithDepends(assetBundleName)); 140 | EditorUtility.DisplayProgressBar("Check the dependencies", assetBundleName, (float)idx / (float)assetBundleNames.Length * 2.0f); 141 | ++idx; 142 | } 143 | foreach (var dependInfo in infoDictionary.Values) 144 | { 145 | if (dependInfo.dependsAssetBundleList == null) 146 | { 147 | ++idx; 148 | continue; 149 | } 150 | foreach (var depend in dependInfo.dependsAssetBundleList) 151 | { 152 | infoDictionary[depend].AddUseThisAssetBundleList(dependInfo.assetBundleName); 153 | } 154 | EditorUtility.DisplayProgressBar("Check the dependencies", dependInfo.assetBundleName, (float)idx / (float)assetBundleNames.Length * 2.0f); 155 | ++idx; 156 | } 157 | // remove no depends 158 | List dataList = new List(infoDictionary.Values); 159 | foreach (var data in dataList) 160 | { 161 | if (data.isNonDepend) 162 | { 163 | infoDictionary.Remove(data.assetBundleName); 164 | allAsssetBundleInfo.noDependList.Add(data); 165 | } 166 | } 167 | #if ASSET_BUNDLE_GROUPING_DEBUG 168 | UnityEngine.Debug.Log("dependBundles : " + infoDictionary.Count + ":: noDependBundles" + (dataList.Count - infoDictionary.Count)); 169 | #endif 170 | // Grouping 171 | EditorUtility.DisplayProgressBar("Grouping...", "", 0.0f); 172 | 173 | int leftAssetBundles = infoDictionary.Count; 174 | int currentGroupId = 0; 175 | HashSet groupHashSet = new HashSet(); 176 | while (infoDictionary.Count > 0) 177 | { 178 | var enumrator = infoDictionary.Values.GetEnumerator(); 179 | enumrator.MoveNext(); 180 | AssetBundleInfoWithDepends currentValue = enumrator.Current; 181 | if (currentValue == null) 182 | { 183 | continue; 184 | } 185 | currentValue.groupId = currentGroupId; 186 | groupHashSet.Clear(); 187 | groupHashSet.Add(currentValue.assetBundleName); 188 | 189 | 190 | 191 | while (currentValue != null) 192 | { 193 | currentValue.groupId = currentGroupId; 194 | if (currentValue.dependsAssetBundleList != null) 195 | { 196 | foreach (var depend in currentValue.dependsAssetBundleList) 197 | { 198 | groupHashSet.Add(depend); 199 | } 200 | } 201 | if (currentValue.useThisAssetBundleList != null) 202 | { 203 | foreach (var used in currentValue.useThisAssetBundleList) 204 | { 205 | groupHashSet.Add(used); 206 | } 207 | } 208 | bool flag = false; 209 | currentValue = null; 210 | foreach (string assetBundle in groupHashSet) 211 | { 212 | if (infoDictionary.TryGetValue(assetBundle, out currentValue)) 213 | { 214 | if (currentValue != null && currentValue.groupId < 0) 215 | { 216 | flag = true; 217 | break; 218 | } 219 | } 220 | else 221 | { 222 | UnityEngine.Debug.LogError("Something wrong " + assetBundle + " @ " + currentGroupId); 223 | } 224 | } 225 | if (!flag) 226 | { 227 | currentValue = null; 228 | } 229 | } 230 | // remove from dictionary 231 | #if ASSET_BUNDLE_GROUPING_DEBUG 232 | string debugPrint = "current Group " + currentGroupId + " num:" + groupHashSet.Count; 233 | #endif 234 | List groupBundleList = new List(groupHashSet.Count); 235 | foreach (string assetBundleName in groupHashSet) 236 | { 237 | #if ASSET_BUNDLE_GROUPING_DEBUG 238 | debugPrint += "\n " + assetBundleName; 239 | #endif 240 | AssetBundleInfoWithDepends assetBundleInfo; 241 | if (infoDictionary.TryGetValue(assetBundleName, out assetBundleInfo)) 242 | { 243 | groupBundleList.Add(assetBundleInfo); 244 | infoDictionary.Remove(assetBundleName); 245 | } 246 | } 247 | allAsssetBundleInfo.dependGroup.Add(currentGroupId, groupBundleList); 248 | 249 | #if ASSET_BUNDLE_GROUPING_DEBUG 250 | UnityEngine.Debug.Log(debugPrint); 251 | #endif 252 | 253 | ++currentGroupId; 254 | EditorUtility.DisplayProgressBar("Grouping...", "Group " + currentGroupId, (-infoDictionary.Count + leftAssetBundles) / (float)leftAssetBundles); 255 | } 256 | 257 | EditorUtility.ClearProgressBar(); 258 | 259 | return allAsssetBundleInfo; 260 | } 261 | 262 | private static AssetBundleBuild CreateAssetBundleBuildFromAssetBundleName(string assetBundleName) 263 | { 264 | AssetBundleBuild build = new AssetBundleBuild(); 265 | 266 | string bundleName; 267 | string variant; 268 | GetAssetBundleNameAndVariantByReservedVariants(assetBundleName, out bundleName, out variant); 269 | 270 | build.assetBundleName = bundleName; 271 | build.assetBundleVariant = variant; 272 | build.assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleName); 273 | return build; 274 | } 275 | 276 | private static void GetAssetBundleNameAndVariantByReservedVariants(string originAssetBundleName, out string assetBundleName, out string assetBundleVariant) 277 | { 278 | assetBundleName = originAssetBundleName; 279 | assetBundleVariant = ""; 280 | 281 | string extension = Path.GetExtension(assetBundleName); 282 | if (!string.IsNullOrEmpty(extension)) 283 | { 284 | extension = extension.Substring(1); 285 | if (ReservedVariants.Contains(extension)) 286 | { 287 | assetBundleName = Path.Combine(Path.GetDirectoryName(assetBundleName), Path.GetFileNameWithoutExtension(assetBundleName)); 288 | assetBundleVariant = extension; 289 | } 290 | } 291 | } 292 | 293 | } 294 | 295 | } -------------------------------------------------------------------------------- /Assets/SeparatedAssetBundleBuild/Editor/SeparatedAssetBundleBuild.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d4d20c950b7476a4a992ebedb52c4cae 3 | timeCreated: 1487234706 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Unity Technologies Japan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.1p2 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityAdsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/UnityAdsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /README.ja.md: -------------------------------------------------------------------------------- 1 | # SeparatedAssetBundleBuild 2 | 大量のAssetBundleをUnity5.5でビルドした時に、異様に時間が掛かってしまう件のワークアラウンドになります。 3 | 4 | Read this in other languages: [English](README.md), 日本語
5 | 6 | 7 | ## 発生している問題について 8 | Unity 5.5にて、ビルド対象のAssetBundle数が増えれば増えるほど、ビルド時間が指数的に長くなるという問題が起きています。
9 | 10 | 図1.AssetBundle数とBuild時間の関係
11 | 12 | ![Alt text](/doc/img/AssetBundleBuildTime.png) 13 | 14 | Issue Tracker:
15 | https://issuetracker.unity3d.com/issues/drastically-longer-asset-bundle-building-time-when-building-multiple-small-asset-bundles
16 | (こちらの問題は、Unity 5.5.3p2/5.6.0p2にて修正されました。) 17 | 18 | ## このプロジェクトについて 19 | このプロジェクトは、"BuildPipeline.BuildAssetBundles"を可能な限り分割して呼び出す事でビルド時間を短縮するためのプロジェクトです。 20 | 21 | 図2.このプロジェクト使用時のAssetBundle数とBuild時間の関係 22 | ![Alt text](/doc/img/WorkAroundBuildTime.png) 23 | 24 | 25 | ### 使用方法 26 | 1). SeparatedAssetBundleBuild.unitypackage をインポートします。
27 | 2). Project内の "BuildPipeline.BuildAssetBundles" -> "UTJ.SeparatedAssetBundleBuild.BuildAssetBundles" と置き換えてください。
28 | ※シングルマニフェストファイルも分割されてして出力されてしまいますので、注意してください。 29 | 30 | ### サンプルについて 31 | テスト用にサンプルを用意しました。
32 | Menuの"Sample/SampleWindow"を呼び出してください。
33 | 34 | ![Alt text](/doc/img/SampleWindow.png)
35 |
36 | 1).テストに使用するアセットバンドル数をセットします。
37 | 2).テスト用のデータを作成します。
38 | 3).従来のやり方でAssetBundleを作成します。
39 | 4).今回用意した方法で、AssetBundleを作成します。
40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SeparatedAssetBundleBuild 2 | Workaround for long time to build many AssetBundles. 3 | 4 | Read this in other languages: English, [日本語](README.ja.md)
5 | 日本語版はコチラを参照してください。 6 | 7 | ## about Issue 8 | At Unity 5.5 , the build time of AssetBundle is increasing exponentially by the number of AssetBundle.
9 | 10 | Graph1.releation between the number of AssetBundles and building time
11 | 12 | Issue Tracker:
13 | https://issuetracker.unity3d.com/issues/drastically-longer-asset-bundle-building-time-when-building-multiple-small-asset-bundles
14 | (This issue was fixed at Unity 5.5.3p2/5.6.0p2) 15 | 16 | ## about this 17 | This is a workaround project.
18 | 19 | To make the build time shorter, it is effective way to separate calling "BuildPipeline.BuildAssetBundles". 20 | 21 | Graph2.this workaround 22 | ![Alt text](/doc/img/AssetBundleBuildTime.png) 23 | 24 | 25 | ### How to use this 26 | 1). Import the "SeparatedAssetBundleBuild.unitypackage".
27 | 2). Replace "BuildPipeline.BuildAssetBundles" to "UTJ.SeparatedAssetBundleBuild.BuildAssetBundles".
28 | *Single manifest file will be the last build's one. 29 | 30 | ### About sample 31 | We prepared test case.
32 | Call "Sample/SampleWindow" from menu.
33 | 34 | ![Alt text](/doc/img/SampleWindow.png)
35 |
36 | 1)The number of datas.
37 | 2).Create test datas.
38 | 3).Build assetBundle without this workaround.
39 | 4).Build assetBundle with this workaround.
40 | 41 | -------------------------------------------------------------------------------- /SeparatedAssetBundleBuild.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/SeparatedAssetBundleBuild.unitypackage -------------------------------------------------------------------------------- /doc/img/AssetBundleBuildTime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/doc/img/AssetBundleBuildTime.png -------------------------------------------------------------------------------- /doc/img/SampleWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/doc/img/SampleWindow.png -------------------------------------------------------------------------------- /doc/img/WorkAroundBuildTime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unity3d-jp/SeparatedAssetBundleBuild/7b88b8cc6bf5aa0d68a325a4fe119bb987ba1b84/doc/img/WorkAroundBuildTime.png --------------------------------------------------------------------------------