AssetBundle打包好后,还需要真正地把游戏Build出来,Unity也提供了BuildPlayer
的API,我们可以根据需要进行处理。比如将APK打在哪里,打包APK前需要设置哪些参数等等。这些也是公共打包机的主要工作。
文件夹准备
首先我们要在Unity工程文件夹下新建几个文件夹,注意Unity工程文件夹是Asset文件夹的父文件夹,没有meta文件。
新建BuildTarget文件夹,再在其内部新建Windows、IOS、Android三个文件夹。
新建AssetBundle文件夹。
修改BundleEditor脚本
我们将BundleEditor
打AB包的路径m_BundleTargetPath
给修改了,然后在BuildAssetBundle
方法内添加一些代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| private static string ABCONFIGPATH = "Assets/ResFrame.Editor/Editor/Resource/ABConfig.asset"; private static string BYTEPATH = "Assets/GameData/Data/ABData/AssetBundleConfig.bytes"; private static string m_BundleTargetPath = Application.dataPath + "/../AssetBundle/" + EditorUserBuildSettings.activeBuildTarget.ToString();
static void BuildAssetBundle() { if(!Directory.Exists(m_BundleTargetPath)) { Directory.CreateDirectory(m_BundleTargetPath); } DeleteAB(); WriteData(resPathDic);
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles ( m_BundleTargetPath, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget ); if (manifest == null) { Debug.LogError("AssetBundle 打包失败"); }else { Debug.Log("打包完毕"); } DeleteManifest(); } static void DeleteManifest() { DirectoryInfo directoryInfo = new DirectoryInfo(m_BundleTargetPath); FileInfo[] fileInfos = directoryInfo.GetFiles("*",SearchOption.AllDirectories); foreach (FileInfo fileInfo in fileInfos) { if (fileInfo.Name.EndsWith(".manifest")) { File.Delete(fileInfo.FullName); } } }
|
添加BuildApp脚本
我们在Editor文件夹下新建BuildApp
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| using System.Collections.Generic; using UnityEngine; using UnityEditor; using System; using System.IO;
public class BuildApp { public static string m_AndroidPath = Application.dataPath + "/../BuildTarget/Android/"; public static string m_IOSPath = Application.dataPath + "/../BuildTarget/IOS/"; public static string m_WindowsPath = Application.dataPath + "/../BuildTarget/Windows/"; [MenuItem("Build/标准包")] public static void Build() { BundleEditor.Build(); string abPath = Application.dataPath + "/../AssetBundle/" + EditorUserBuildSettings.activeBuildTarget.ToString() + "/"; Copy(abPath, Application.streamingAssetsPath); string savePath = ""; if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android) { savePath = m_AndroidPath + PlayerSettings.productName + "_" + EditorUserBuildSettings.activeBuildTarget.ToString()+ "_" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm") + ".apk"; } else if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS) { savePath = m_IOSPath + PlayerSettings.productName + "_" + EditorUserBuildSettings.activeBuildTarget.ToString()+ "_" + DateTime.Now.ToString("yyyy-MM-dd-HH-mm"); } else if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows64 || EditorUserBuildSettings.activeBuildTarget == BuildTarget.StandaloneWindows) { savePath = m_WindowsPath + PlayerSettings.productName + "_" + EditorUserBuildSettings.activeBuildTarget.ToString() + string.Format("_{0:yyyy_MM_dd_HH_mm}/{1}.exe", DateTime.Now,PlayerSettings.productName); } BuildPipeline.BuildPlayer(FindEnabledEditorScenes(),savePath,EditorUserBuildSettings.activeBuildTarget,BuildOptions.None);
DeleteDir(Application.streamingAssetsPath); }
private static string[] FindEnabledEditorScenes() { List<string> editorScenes = new List<string>(); foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes) { if(!scene.enabled) continue; editorScenes.Add(scene.path); } return editorScenes.ToArray(); } private static void Copy(string srcPath, string targetPath) { try { if(!Directory.Exists(targetPath)) { Directory.CreateDirectory(targetPath); } string srcdir = Path.Combine(targetPath,Path.GetFileName(srcPath)); if (Directory.Exists(srcPath)) { srcdir += Path.DirectorySeparatorChar; } if (!Directory.Exists(srcdir)) { Directory.CreateDirectory (srcdir); } string[] filePaths = Directory.GetFileSystemEntries(srcPath); foreach (var filePath in filePaths) { if (Directory.Exists(filePath)) { Copy(filePath, srcdir); } else { File.Copy(filePath,srcdir + Path.GetFileName(filePath),true); } } } catch { Debug.LogError("无法复制:" + srcPath + " 到" + targetPath); } }
private static void DeleteDir(string path) { try { DirectoryInfo dirInfo = new DirectoryInfo(path); FileSystemInfo[] fileSysInfos = dirInfo.GetFileSystemInfos(); foreach (FileSystemInfo fileSystemInfo in fileSysInfos) { if (fileSystemInfo is DirectoryInfo) { DirectoryInfo subdir = new DirectoryInfo(fileSystemInfo.FullName); subdir.Delete(true); } else { File.Delete(fileSystemInfo.FullName); } } } catch (Exception e) {
Debug.LogException(e); } } }
|
Build流程梳理
- 首先在工程文件的AssetBundle文件夹内生成AB包,生成在这里是为了不让AssetBundle参与版本管理,在开发阶段让AssetBundle参与版本管理没有必要。
- 然后把生成的AB包复制到Asset/StreamingAssets文件夹下面(也即是
BuildApp.Copy
方法的用处),因为不复制进来的话Build的时候需要的资源就没有了。
- 根据当前的平台进行Build,注意我们每次Build的成果都会根据日期归档。
- 删除Asset/StreamingAssets文件夹下的AB包,还是为了不让AssetBundle参与版本管理。
修改AssetBundleManager
由于我们修改了AssetBundle的构建流程,我们的AssetBundleManager
一些API就必须要修改
1 2 3 4 5 6 7 8 9 10
| public bool LoadAssetBundleConfig() { #if UNITY_EDITOR if(!ResourceManager.Instance.m_LoadFromAssetBundle) return false; #endif m_ResourceItemDic.Clear(); }
|