/// <summary> /// Copies built asset bundles to the StreamingAssets folder. /// </summary> public static void CopyToStreamingAssets() { if (!string.IsNullOrEmpty(DistDirectory)) { try { string srcDirectory = DistDirectory; string[] files = Directory.GetFiles(srcDirectory); if (srcDirectory.StartsWith("./")) { srcDirectory = srcDirectory.Substring(2); // makes entire string indifferent to absolute and relative paths } foreach (string sourceFilename in files) { string destFileName = Builder.TARGET_IN_STREAMING_ASSETS + sourceFilename.Substring(sourceFilename.IndexOf(srcDirectory) + srcDirectory.Length); ETUtils.CreateDirectoryForFile(destFileName); File.Copy(sourceFilename, destFileName, true); } } catch (Exception e) { // TODO: introduce logger like in the Builder // - to replace all Console.Write*; // - to inform TeamCity about the error (otherwise throw an exception). Console.WriteLine("Caught exception, while copying files to StreamingAssets: " + e.ToString()); } AssetDatabase.Refresh(); // makes sure asset bundles would be included in the build } else { Console.WriteLine("WARNING. Can't copy artifacts, because nothing has been built by use of BuilderHelper."); } }
/// <summary> /// Separate bundles into two folders: compressed and uncompressed /// </summary> public static void SeparateBundles() { if (!string.IsNullOrEmpty(DistDirectory)) { try { string srcDirectory = DistDirectory; string[] files = Directory.GetFiles(srcDirectory); if (srcDirectory.StartsWith("./")) { srcDirectory = srcDirectory.Substring(2); // makes entire string indifferent to absolute and relative paths } string destUnCompressedDir = srcDirectory + "/Uncompressed"; string destCompressedDir = srcDirectory + "/Compressed"; foreach (string sourceFilename in files) { string destFileName; string srcFileName = Path.GetFileName(sourceFilename); Console.WriteLine("Source file name = " + srcFileName); if (Builder.uncompressedBundleList.Contains(srcFileName)) { destFileName = Path.Combine(destUnCompressedDir, srcFileName); } else { destFileName = Path.Combine(destCompressedDir, srcFileName); } //index files are not in list, but they must exist in both folders. if (srcFileName.StartsWith("index")) { string fn = Path.Combine(destUnCompressedDir, srcFileName); ETUtils.CreateDirectoryForFile(fn); File.Copy(sourceFilename, fn); } ETUtils.CreateDirectoryForFile(destFileName); File.Move(sourceFilename, destFileName); } } catch (Exception e) { Console.WriteLine("Caught exception, while copying files to StreamingAssets: " + e.Message); } AssetDatabase.Refresh(); // makes sure asset bundles would be included in the build } else { Console.WriteLine("WARNING. Can't copy artifacts, because nothing has been built by use of BuilderHelper."); } }
// TODO: comment it: computes hash of the asset bundle based on the specified assets public static string ComputeAssetBundleHashDependingOnProvidedDistribution(Index index, Index.AssetBundle assetBundle) { Index.AssetBundle userAssetBundle = assetBundle; Index.AssetBundle realAssetBundle = null; foreach (Index.AssetBundle ab in index.m_assetBundles) { if (ab.m_filename.Equals(userAssetBundle.m_filename)) { realAssetBundle = ab; break; } } Assertion.Check(realAssetBundle != null); // SANITY CHECK // create a list contained user-defined assets (they could become just references) List <string> references = new List <string>(); foreach (Index.AssetBundle.Asset asset in userAssetBundle.m_assets) { references.Add(asset.m_filename); } // now compute hash for the asset bundle string ret = ""; foreach (Index.AssetBundle.Asset asset in realAssetBundle.m_assets) { string hash = File.Exists(asset.m_filename) ? ETUtils.CreateHashForAsset(asset.m_filename) : null; // hash of the content ret = ETUtils.HashXorHash(ret, hash); } foreach (string assetFilepath in references) { string hash = ETUtils.CreateHashForString(assetFilepath); // hash of explicit asset name ret = ETUtils.HashXorHash(ret, hash); } return(ret); // return null to compute hashes with base (incorrent) algorithm }
/// <summary> /// Cleans the StreamingAssets folder from generated asset bundles. /// </summary> public static void CleanStreamingAssets() { ETUtils.DeleteDirectory(Builder.TARGET_IN_STREAMING_ASSETS); ETUtils.CreateDirectory(Builder.TARGET_IN_STREAMING_ASSETS); AssetDatabase.Refresh(); }
/// <summary> /// Builds asset bundles. /// </summary> public static void Build( ref List <string> scenesToBuild, ref BuildTarget buildTarget, ref BuildOptions buildOptions, IBuildConfig buildConfig, string originalIndexFilename, string producedIndexFilename, bool?compressAssetBundles) { // set output folder Assertion.Check(buildConfig != null, "BuildConfig must be specified!"); InitDistDirectory(buildConfig); // configure builder Index index = Builder.index; Builder.index = null; // means, build all found indices if (!string.IsNullOrEmpty(originalIndexFilename)) { bool found = false; Index[] indices = Builder.GetIndexInstances(); Builder.index = index; // restores original value foreach (Index i in indices) { if (i.m_filename.ToLower().Equals(originalIndexFilename.ToLower())) { Builder.index = i; found = true; break; } } Assertion.Check(found, "Index \"{0}\" has not been found!", originalIndexFilename); if (!found) { throw new NotSupportedException(string.Format("Index \"{0}\" has not been found. No asset bundles will be built.", originalIndexFilename)); } } Index.m_overridenFilenameMask = producedIndexFilename; bool buildReadableIndex = Builder.BuildReadableIndex; Builder.BuildReadableIndex = ETUtils.IsUnityInBatchMode(); // means, on buildmachines only Builder.AssetBundlesCompressionOverriding overrideAssetBundlesCompression = Builder.OverrideAssetBundlesCompression; if ((compressAssetBundles != null) && compressAssetBundles.HasValue) { Builder.OverrideAssetBundlesCompression = compressAssetBundles.Value ? Builder.AssetBundlesCompressionOverriding.Compressed : Builder.AssetBundlesCompressionOverriding.Uncompressed; } else { Builder.OverrideAssetBundlesCompression = Builder.AssetBundlesCompressionOverriding.DoNotOverride; } // produce bundles UpdateScenes(ref scenesToBuild); Builder.BuildAssetBundles(DistDirectory, buildTarget, buildOptions); // restore builder Builder.index = index; Index.m_overridenFilenameMask = null; Builder.BuildReadableIndex = buildReadableIndex; Builder.OverrideAssetBundlesCompression = overrideAssetBundlesCompression; }
// TODO: comment it: gets distribution (which assets in which bundles) in reality public static Index ReorganizeDistribution(Index index) { Dictionary <string, Index.AssetBundle> userAssetsToBundles = GetUserDistribution(index); Dictionary <string, Index.AssetBundle> realAssetsToBundles = GetRealDistribution(userAssetsToBundles); Dictionary <string, List <string> > dist = new Dictionary <string, List <string> >(); foreach (KeyValuePair <string, Index.AssetBundle> kvp in realAssetsToBundles) { if (!dist.ContainsKey(kvp.Value.m_filename)) { dist.Add(kvp.Value.m_filename, new List <string>()); } dist[kvp.Value.m_filename].Add(kvp.Key); } index = Index.DuplicateInstance(index); HashSet <Index.AssetBundle> checkedAssetBundles = new HashSet <Index.AssetBundle>(); HashSet <Index.AssetBundle.Asset> checkedAssets = new HashSet <Index.AssetBundle.Asset>(); foreach (KeyValuePair <string, List <string> > kvp in dist) { Index.AssetBundle assetBundle = null; foreach (Index.AssetBundle ab in index.m_assetBundles) { if (ab.m_filename.Equals(kvp.Key)) { assetBundle = ab; break; } } Assertion.Check(assetBundle != null); if (assetBundle != null) { foreach (string val in kvp.Value) { Index.AssetBundle.Asset asset = null; foreach (Index.AssetBundle.Asset a in assetBundle.m_assets) { if (a.m_filename.Equals(val)) { asset = a; break; } } if (asset == null) { asset = new Index.AssetBundle.Asset(); asset.m_filename = val; asset.m_guid = AssetDatabase.AssetPathToGUID(asset.m_filename); assetBundle.m_assets.Add(asset); } asset.m_hash = File.Exists(asset.m_filename) ? ETUtils.CreateHashForAsset(asset.m_filename) : null; checkedAssets.Add(asset); } checkedAssetBundles.Add(assetBundle); } } foreach (Index.AssetBundle assetBundle in index.m_assetBundles) { if (checkedAssetBundles.Contains(assetBundle)) { for (int idx = assetBundle.m_assets.Count - 1; idx >= 0; --idx) { if (!checkedAssets.Contains(assetBundle.m_assets[idx])) { assetBundle.m_assets.RemoveAt(idx); } } } else { assetBundle.m_assets.Clear(); } } return(index); }