/// <summary> /// 因为编辑器下更改static属性有时会变成"",因此使用前调用此函数进行初始化 /// </summary> /// <param name="appInfoConfig"></param> public static void InitABBuildPath(AF_ABConfig aBConfig) { switch (aBConfig.packageABType) { case PackageABType.StreamingAssetAB: ABTargetPath = GetStreamingAssetABPath(aBConfig); ABInfoPath = GetStreamingAssetInfoPath(aBConfig, true); AppInfoPath = ABInfoPath + "APPInfo.txt"; break; case PackageABType.PhoneAB: AppInfoPath = PathTool.ProjectPath + "AF-ABForPhone/" + "/APPInfo.txt"; ABTargetPath = PathTool.ProjectPath + "AF-ABForPhone/" + "/"; //再根据类型拷贝AB包 ABInfoPath = PathTool.ProjectPath + "AF-ABForPhone/" + "/"; break; case PackageABType.ServerAB: if (aBConfig.isDevelopOrOnlineAB) { AppInfoPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/APPInfo.txt"; ABTargetPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/AF-ABResource" + aBConfig.ABDevelopmentVersion + "/"; ABInfoPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/AF-InfoFile" + aBConfig.ABDevelopmentVersion + "/"; } else { AppInfoPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/APPInfo.txt"; ABTargetPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/AF-ABResource" + aBConfig.ABOnlineVersion + "/"; ABInfoPath = PathTool.ProjectPath + "AF-ABForServer/" + aBConfig.CurrentAppType.ToString() + "/AF-InfoFile" + aBConfig.ABOnlineVersion + "/"; } break; } }
public static void UpdateABClass() { string ABConfigPath = AssetDatabasex.GetAssetPathStr("AF_ABConfig"); AF_ABConfig abConfig = null; if (!ABConfigPath.IsNotNullAndEmpty()) { abConfig = new AF_ABConfig(); ABConfigPath = "Assets/Scripts/AFData/AF-ConfigPath/AF_ABConfig.asset"; } else { abConfig = AssetDatabase.LoadAssetAtPath <AF_ABConfig>(ABConfigPath); } foreach (ARForProductType aBClass in System.Enum.GetValues(typeof(ARForProductType))) { if (abConfig != null && abConfig.JudgeClassExit(aBClass)) { continue; } AF_ABOneClass aF_ABOneClass = new AF_ABOneClass(); aF_ABOneClass.ABClassType = aBClass.ToString(); abConfig.m_AllClass.Add(aF_ABOneClass); } if (!FileHelper.JudgeFilePathExit(System.Environment.CurrentDirectory + "/" + ABConfigPath)) { AssetDatabase.CreateAsset(abConfig, ABConfigPath); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } }
public static string GetStreamingAssetInfoPath(AF_ABConfig aBConfig, bool isCompletePath) { string temp = ""; if (isCompletePath) #if UNITY_EDITOR { temp = PathTool.ProjectPath + "Assets/Resources/AF-ABForLocal/AF-InfoFile"; } #else { temp = ""; }
public static string GetStreamingAssetABPath(AF_ABConfig aBConfig) { if (aBConfig.isDevelopOrOnlineAB) { return(PathTool.StreamingAssetsPath + "AF-ABForLocal/AF-ABResource" + aBConfig.ABDevelopmentVersion + "/"); } else { return(PathTool.StreamingAssetsPath + "AF-ABForLocal/AF-ABResource" + aBConfig.ABOnlineVersion + "/"); } }
bool CommonBuildSetting() { if ((buildPlatform == BuildPlatform.Android && AndroidAPKPath == "") || (buildPlatform == BuildPlatform.IOS && XCodeProjectPath == "")) { AFLogger.EditorErrorLog("APP目标打包路径不能为空"); return(false); } EditorUserBuildSettings.development = DevelopmentBuild; PlayerSettings.productName = DisplayName; AF_ABConfig ABConfig = AssetDatabasex.LoadAssetOfType <AF_ABConfig>("AF_ABConfig"); return(true); }
/// <summary> /// 获取info保存路径 /// </summary> /// <param name="aBConfig"></param> /// <returns></returns> public static string GetInfoPath(AF_ABConfig aBConfig, bool isCompletePath, ABResLoadFrom ABResLoadfrom) { switch (ABResLoadfrom) { case ABResLoadFrom.EditorRes: return(""); case ABResLoadFrom.StreamingAssetAB: return(GetStreamingAssetInfoPath(aBConfig, isCompletePath)); #if UNITY_EDITOR case ABResLoadFrom.PersistentDataPathAB: return(PathTool.ProjectPath + "AF-ABForServer/AF-InfoFile" + aBConfig.ABDevelopmentVersion + "/"); #endif } return(""); }
static void BunildAssetBundle(AF_ABConfig abConfig) { string[] allBundles = AssetDatabase.GetAllAssetBundleNames(); //key : 为全路径 value :为名字 Dictionary <string, string> resPathDic = new Dictionary <string, string>(); for (int i = 0; i < allBundles.Length; i++) { string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]); for (int j = 0; j < allBundlePath.Length; j++) { //判断有没有包含脚本文件 if (allBundlePath[j].EndsWith(".cs")) { continue; } //Debug.Log("此AB包:" + allBundles[i] + "下面包含的资源文件路径:" + allBundlePath[j]); if (ValidPath(allBundlePath[j])) { resPathDic.Add(allBundlePath[j], allBundles[i]); } } } //现在已经设置好了在这一次要打包的AB包,因此要清除无用的AB包,比如之前存在的AB包 DeleteAB(); //生成自己的配置表 WriteData(resPathDic, abConfig.configWritingMode, abConfig.packageABType); AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(m_BundleTargetPath, BuildAssetBundleOptions.ChunkBasedCompression, buildTarget); if (manifest == null) { AFLogger.EditorErrorLog("AssetBundle" + buildTarget.ToString() + "打包失败,请检查设置!"); } else { AFLogger.d("AssetBundle" + buildTarget.ToString() + "打包完毕"); } }
public void AutoAddTarget() { if (TargetDataSetName.IsNullOrEmpty()) { AFLogger.EditorErrorLog("DataSet名称为空!"); return; } AF_ABConfig ABConfig = AssetDatabasex.LoadAssetOfType <AF_ABConfig>("AF_ABConfig"); char[] t = ABConfig.defaultDataSetPath.ToCharArray(); string xmlPath = ABConfig.defaultDataSetPath; if (t[t.Length - 1] == '/') { xmlPath += TargetDataSetName + ".xml"; } else { xmlPath += "/" + TargetDataSetName + ".xml"; } if (xmlPath == "") { AFLogger.d("未找到DataSet对应的xml文件,请检查m_AllFileAB中是否有配置CategoryOfOwnership为" + ABClassType + "且isHasDataset为true"); return; } if (mImagetTargetInfo == null) { mImagetTargetInfo = new List <OneTargetInfo>(); } List <string> allRecogTarget = AFSDK_DataSetHandle.GetDataSetTarget(xmlPath); if (allRecogTarget == null) { AFLogger.EditorErrorLog("解析xml失败!"); return; } for (int j = mImagetTargetInfo.Count - 1; j >= 0; j--) { bool isNeedRemove = true; for (int i = allRecogTarget.Count - 1; i >= 0; i--) { if (mImagetTargetInfo[j].ImageTargetName.Equals(allRecogTarget[i])) { isNeedRemove = false; allRecogTarget.RemoveAt(i); break; } } if (isNeedRemove) { mImagetTargetInfo.RemoveAt(j); } } foreach (string recogName in allRecogTarget) { OneTargetInfo oneTargetInfo = new OneTargetInfo(); oneTargetInfo.ImageTargetName = recogName; oneTargetInfo.oneResInfo.ResScale = new Vector3(1, 1, 1); mImagetTargetInfo.Add(oneTargetInfo); } }
public static void Build() { m_BundleTargetPath = EditorAssetPath.ProjectPath + "AssetBundle/" + buildTarget.ToString() + "/"; AppInfoConfig appInfoConfig = AssetDatabasex.LoadAssetOfType <AppInfoConfig>("AppInfoConfig"); AF_ABConfig abConfig = AssetDatabasex.LoadAssetOfType <AF_ABConfig>("AF_ABConfig"); EditorAssetPath.InitABBuildPath(abConfig); //清空 m_ConfigFile.Clear(); m_AllFileAB.Clear(); m_AllFileDir.Clear(); m_AllPrefabDir.Clear(); string mTargetPath = EditorAssetPath.ABTargetPath; string mInfoPath = EditorAssetPath.ABInfoPath; if (abConfig.packageABType != PackageABType.PhoneAB) { mTargetPath = EditorAssetPath.ABTargetPath + buildTarget.ToString() + "/"; mInfoPath = EditorAssetPath.ABInfoPath + buildTarget.ToString() + "/"; } if (Directory.Exists(mTargetPath)) { FileUtil.DeleteFileOrDirectory(mTargetPath); } if (Directory.Exists(mInfoPath)) { FileUtil.DeleteFileOrDirectory(mInfoPath); } Directory.CreateDirectory(mInfoPath); Directory.CreateDirectory(mTargetPath); Directory.CreateDirectory(m_BundleTargetPath); //创建APP版本文件 FileHelper.CreatFile(EditorAssetPath.AppInfoPath, SerializeHelper.ToByteArray(appInfoConfig), true); Dictionary <string, bool> ClassToNeedPackageAB = new Dictionary <string, bool>(); for (int i = 0; i < abConfig.m_AllClass.Count; i++) { if (abConfig.m_AllClass[i].isSameAppType(abConfig.CurrentAppType)) { ClassToNeedPackageAB.Add(abConfig.m_AllClass[i].ABClassType, abConfig.m_AllClass[i].isNeedPackageAB); } } //剔除重复路径,将单个文件及文件夹的路径保存下来 //先处理文件夹再处理单个文件,因为有可能prefab依赖某个文件中的东西,所以要进行过滤 foreach (AF_OneAB oneAB in abConfig.m_AllFileAB) { bool isNeedPackageAB = false; for (int k = 0; k < oneAB.CategoryOfOwnership.Count; k++) { if (ClassToNeedPackageAB.ContainsKey(oneAB.CategoryOfOwnership[k]) && ClassToNeedPackageAB[oneAB.CategoryOfOwnership[k]]) { isNeedPackageAB = true; break; } } if (!isNeedPackageAB) { continue; } if (m_AllFileDir.ContainsKey(oneAB.mABIdentifier)) { AFLogger.EditorErrorLog("AB包配置名字重复,请检查!"); EditorUtility.ClearProgressBar(); } else { m_AllFileDir.Add(oneAB.mABIdentifier, oneAB.Path); //保存已打包的AB包路径 m_AllFileAB.Add(oneAB.Path); m_ConfigFile.Add(oneAB.Path); } } string[] AllPrefabsPath = abConfig.GetAllPrefabsPath(); if (AllPrefabsPath.Length > 0) { //获取路径下的所有prefab string[] allStr = AssetDatabase.FindAssets("t:Prefab", AllPrefabsPath); AFLogger.EditorInfoLog("获取的路径长度:" + allStr.Length); for (int i = 0; i < allStr.Length; i++) { bool isNeedPackageAB = false; for (int k = 0; k < abConfig.m_AllPrefabAB[i].CategoryOfOwnership.Count; k++) { if (ClassToNeedPackageAB.ContainsKey(abConfig.m_AllPrefabAB[i].CategoryOfOwnership[k]) && ClassToNeedPackageAB[abConfig.m_AllPrefabAB[i].CategoryOfOwnership[k]]) { isNeedPackageAB = true; break; } } if (!isNeedPackageAB) { continue; } //GUID转asset路径 string path = AssetDatabase.GUIDToAssetPath(allStr[i]); EditorUtility.DisplayProgressBar("查找Prefab", "Prefab:" + path, i * 1.0f / allStr.Length); m_ConfigFile.Add(path); if (!ContainAllFileAB(path)) { //获取资源的所有依赖 string[] allDepend = AssetDatabase.GetDependencies(path); List <string> allDependPath = new List <string>(); //遍历依赖文件 for (int j = 0; j < allDepend.Length; j++) { if (!ContainAllFileAB(allDepend[j]) && !allDepend[j].EndsWith(".cs", System.StringComparison.Ordinal)) { m_AllFileAB.Add(allDepend[j]); allDependPath.Add(allDepend[j]); } } if (m_AllPrefabDir.ContainsKey(abConfig.m_AllPrefabAB[i].mABIdentifier)) { AFLogger.EditorErrorLog("存在相同名字的Prefab!名字:" + abConfig.m_AllPrefabAB[i].mABIdentifier); EditorUtility.ClearProgressBar(); } else { m_AllPrefabDir.Add(abConfig.m_AllPrefabAB[i].mABIdentifier, allDependPath); } } } } //点击打包之后可以看见更改的文件的.meta文件改变 //文件夹设置ABName foreach (string name in m_AllFileDir.Keys) { SetABName(name, m_AllFileDir[name]); } //单个文件设置包名 foreach (string name in m_AllPrefabDir.Keys) { SetABName(name, m_AllPrefabDir[name]); } //打包 BunildAssetBundle(abConfig); //清除AB包名,因为上面更改了.meta文件,我们很多时候会使用svn或者git,有可能会导致一不小心上传特别乱 string[] oldABNames = AssetDatabase.GetAllAssetBundleNames(); for (int i = 0; i < oldABNames.Length; i++) { AssetDatabase.RemoveAssetBundleName(oldABNames[i], true); EditorUtility.DisplayProgressBar("清除AB包名", "名字:" + oldABNames[i], i * 1.0f / oldABNames.Length); } EditorUtility.ClearProgressBar(); //根据设置生成文件 ABBuildFinishEvent.BundleFinish(mTargetPath, m_BundleTargetPath, abConfig, mInfoPath, appInfoConfig); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); }
/// <summary> /// AB包打包完成后执行的函数,这里是将AB包移到指定的路径并生成对应的info文件 /// </summary> /// <param name="mTargetPath">AB包目标路径,可以在ABCommonPath脚本中设置</param> /// <param name="m_BunleTargetPath">AB包初步路径</param> /// <param name="abConfig"></param> /// <param name="mInfoPath">info信息文件路径</param> /// <param name="AppInfoConfig"></param> public static void BundleFinish(string mTargetPath, string m_BunleTargetPath, AF_ABConfig abConfig, string mInfoPath, AppInfoConfig AppInfoConfig) { //一个类别对应的info Dictionary <string, OneABClassInfo> ClassToInfo = new Dictionary <string, OneABClassInfo>(); Dictionary <string, bool> ClassToAppType = new Dictionary <string, bool>(); Dictionary <string, string> ABNameToPath = new Dictionary <string, string>(); for (int i = 0; i < abConfig.m_AllClass.Count; i++) { string classStr = abConfig.m_AllClass[i].ABClassType; ClassToAppType.Add(classStr, abConfig.m_AllClass[i].isSameAppType(abConfig.CurrentAppType)); OneABClassInfo oneClassInfo = new OneABClassInfo(); oneClassInfo.RecogType = abConfig.m_AllClass[i].ARrecogType; switch (oneClassInfo.RecogType) { case ARRecogType.DataSet: List <OneDataSetInfo> dataSetInfos = new List <OneDataSetInfo>(); foreach (OneDataSet oneDataSet in abConfig.m_AllClass[i].dataSetList) { OneDataSetInfo oneDataSetInfo = new OneDataSetInfo(); oneDataSetInfo.TargetDataSet = oneDataSet.TargetDataSetName; //记录识别图资料 oneDataSetInfo.TargetInfo = new Dictionary <string, OneTargetInfo>(); char[] t = abConfig.defaultDataSetPath.ToCharArray(); string dataSetPath = abConfig.defaultDataSetPath; if (t[t.Length - 1] != '/') { dataSetPath += "/"; } string targetDataSetName = oneDataSet.TargetDataSetName; string xmlMD5 = ""; string datMD5 = ""; if (abConfig.packageABType == PackageABType.StreamingAssetAB) { string vuforiaPath = Application.streamingAssetsPath + "/Vuforia/"; Directory.CreateDirectory(vuforiaPath); //拷贝识别资源 if (!FileHelper.CopyFile(dataSetPath + targetDataSetName + ".xml", vuforiaPath + targetDataSetName + ".xml")) { break; } xmlMD5 = FileHelper.getFileHash(vuforiaPath + targetDataSetName + ".dat"); if (!FileHelper.CopyFile(dataSetPath + targetDataSetName + ".dat", vuforiaPath + targetDataSetName + ".dat")) { break; } datMD5 = FileHelper.getFileHash(vuforiaPath + targetDataSetName + ".xml"); if (!oneClassInfo.ABName.ContainsKey(targetDataSetName + ".xml") && !oneClassInfo.ABName.ContainsKey(targetDataSetName + ".dat")) { //将识别资源添加到ABName中,因为也是要下载的,同时记录其大小 oneClassInfo.ABName.Add(targetDataSetName + ".xml", FileHelper.GetFileSize(vuforiaPath + targetDataSetName + ".xml")); oneClassInfo.ABName.Add(targetDataSetName + ".dat", FileHelper.GetFileSize(vuforiaPath + targetDataSetName + ".dat")); } } else { //拷贝识别资源 if (!FileHelper.CopyFile(dataSetPath + targetDataSetName + ".xml", mTargetPath + targetDataSetName + ".xml")) { break; } xmlMD5 = FileHelper.getFileHash(dataSetPath + targetDataSetName + ".xml"); if (!FileHelper.CopyFile(dataSetPath + targetDataSetName + ".dat", mTargetPath + targetDataSetName + ".dat")) { break; } datMD5 = FileHelper.getFileHash(dataSetPath + targetDataSetName + ".dat"); if (!oneClassInfo.ABName.ContainsKey(targetDataSetName + ".xml") && !oneClassInfo.ABName.ContainsKey(targetDataSetName + ".dat")) { //将识别资源添加到ABName中,因为也是要下载的,同时记录其大小 oneClassInfo.ABName.Add(targetDataSetName + ".xml", FileHelper.GetFileSize(mTargetPath + targetDataSetName + ".xml")); oneClassInfo.ABName.Add(targetDataSetName + ".dat", FileHelper.GetFileSize(mTargetPath + targetDataSetName + ".dat")); } } //添加识别资源的MD5码, if (!oneClassInfo.FileMD5.ContainsKey(targetDataSetName + ".xml") && !oneClassInfo.FileMD5.ContainsKey(targetDataSetName + ".dat")) { // Debug.Log("第一次添加xml MD5:" + CategoryOfOwnershipS + " " + targetDataSetName); oneClassInfo.FileMD5.Add(targetDataSetName + ".xml", xmlMD5); oneClassInfo.FileMD5.Add(targetDataSetName + ".dat", datMD5); } else { //是已经打包过的类别 // Debug.Log("重复添加xml MD5:" + CategoryOfOwnershipS + " " + targetDataSetName); } if (!ABNameToPath.ContainsKey(targetDataSetName + ".xml") && !ABNameToPath.ContainsKey(targetDataSetName + ".dat")) { ABNameToPath.Add(targetDataSetName + ".xml", classStr + "/" + targetDataSetName + ".xml"); ABNameToPath.Add(targetDataSetName + ".dat", classStr + "/" + targetDataSetName + ".dat"); } for (int j = 0; j < oneDataSet.mImagetTargetInfo.Count; j++) { oneDataSetInfo.TargetInfo.Add(oneDataSet.mImagetTargetInfo[j].ImageTargetName, oneDataSet.mImagetTargetInfo[j]); } dataSetInfos.Add(oneDataSetInfo); } oneClassInfo.dataSetInfos = dataSetInfos; break; case ARRecogType.Plane: oneClassInfo.ResInfoForPlane = abConfig.m_AllClass[i].ResInfoForPlane; break; } oneClassInfo.isNeedPackageAB = abConfig.m_AllClass[i].isNeedPackageAB; ClassToInfo.Add(classStr, oneClassInfo); } List <AF_OneAB> allAB = new List <AF_OneAB>(); foreach (AF_OneAB oneAB in abConfig.m_AllFileAB) { allAB.Add(oneAB); } foreach (AF_OneAB oneAB in abConfig.m_AllPrefabAB) { allAB.Add(oneAB); } //遍历 for (int i = 0; i < allAB.Count; i++) { EditorUtility.DisplayProgressBar("整理AB包资源", "名字TargetDataSet:" + allAB[i].mABIdentifier, i * 1.0f / (allAB.Count + abConfig.m_AllPrefabAB.Count)); //分别拷贝到对应的类别中 for (int k = 0; k < allAB[i].CategoryOfOwnership.Count; k++) { string CategoryOfOwnershipS = allAB[i].CategoryOfOwnership[k]; if (!ClassToInfo.ContainsKey(CategoryOfOwnershipS)) { AFLogger.EditorErrorLog(allAB[i].mABIdentifier + "所属类型错误,不在m_AllClass内,请检查"); EditorUtility.ClearProgressBar(); return; } //不是当前APP Type的类型,跳过 if (!ClassToAppType[CategoryOfOwnershipS]) { continue; } if (!ClassToInfo[CategoryOfOwnershipS].isNeedPackageAB) { continue; } string ABIdentifier = allAB[i].mABIdentifier.ToLower(); //拷贝AB包 if (!FileHelper.CopyFile(m_BunleTargetPath + "/" + ABIdentifier, mTargetPath + ABIdentifier)) { break; } //添加AB包的MD5码 string ABMD5 = FileHelper.getFileHash(m_BunleTargetPath + "/" + ABIdentifier); if (!ClassToInfo[CategoryOfOwnershipS].FileMD5.ContainsKey(ABIdentifier)) { ClassToInfo[CategoryOfOwnershipS].FileMD5.Add(ABIdentifier, ABMD5); } //是已经打包过的类别 if (ABNameToPath.ContainsKey(ABIdentifier)) { ABNameToPath.Add(ABIdentifier, CategoryOfOwnershipS + "/" + ABIdentifier); } //保存文件的大小 ClassToInfo[CategoryOfOwnershipS].ABName.Add(ABIdentifier, FileHelper.GetFileSize(mTargetPath + ABIdentifier)); } } //保存info文件 for (int i = 0; i < abConfig.m_AllClass.Count; i++) { if (abConfig.m_AllClass[i].isNeedPackageAB) { SerializeHelper.SaveJson <OneABClassInfo>(ClassToInfo[abConfig.m_AllClass[i].ABClassType.ToString()], mInfoPath + abConfig.m_AllClass[i].ABClassType + "Info.txt"); } } if (abConfig.configWritingMode == ConfigWritingMode.Binary) { FileHelper.DeleteFile(PathTool.ProjectPath + "Assets/AssetbundleConfig.bytes"); FileHelper.CopyFile(m_BunleTargetPath + "assetbundleconfig", mTargetPath + "AssetbundleConfig"); } AssetDatabase.Refresh(); Debug.Log("资源拷贝完毕,保存路径为 : " + mTargetPath); EditorUtility.RevealInFinder(mTargetPath); }
public void ABSysInit(AppInfoConfig appInfo, AF_ABConfig ABConfig) { this.appInfo = appInfo; this.ABConfig = ABConfig; AFLogger.d("ABSysInit"); }