/// <summary> /// Asset打包构造函数 /// </summary> /// <param name="asset">当前Asset</param> /// <param name="dependentasset">依赖使用当前Asset的Asset</param> public PackageAsset(Object asset, Object dependentasset = null) { mAssetObject = asset; if (mAssetObject == null) { mPackageAssetType = AssetPackageType.E_INVALIDE; mAssetAssetBundleBuildRule = AssetABBuildRule.E_INVALIDE; mAssetPath = string.Empty; mDependentPackageAsset = null; mInvalideBuildRuleList = null; } else { mAssetPath = AssetDatabase.GetAssetPath(mAssetObject); mPackageAssetType = ABHelper.Singleton.getAssetPackageType(mAssetPath); mAssetAssetBundleBuildRule = ABHelper.Singleton.getAssetABBuildRule(mAssetPath); if (dependentasset != null) { mDependentPackageAsset = new PackageAsset(dependentasset); } else { mDependentPackageAsset = null; } mInvalideBuildRuleList = new List <AssetABBuildRule>(); mInvalideBuildRuleList.Add(AssetABBuildRule.E_INVALIDE); } }
public void OnGUI() { CurrentPackage = (PackageImport)EditorGUILayout.ObjectField(CurrentPackage, typeof(PackageImport)); var explorer = CurrentPackage.Explorer; foreach (var asset in explorer.Folders) { if (GUILayout.Button(asset.ToString())) { CurrentAsset = asset; HasCurrentAsset = true; CurrentAssetJson = null; } } if (HasCurrentAsset) { if (string.IsNullOrEmpty(CurrentAssetJson)) { var bhvr = FindBhvr(CurrentAsset); Debug.Log(bhvr); CurrentAssetJson = Encoding.UTF8.GetString(bhvr.LoadData()); } CurrentAssetJson = EditorGUILayout.TextArea(CurrentAssetJson); } }
/// <summary> /// 显示资源的最终AB名字结论 /// </summary> /// <param name="pa"></param> private void showAssetABNameUI(PackageAsset pa) { GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Asset path : {0}", pa.AssetPath), GUILayout.Width(700.0f)); GUILayout.Label(string.Format("Asset BuildRule : {0}", pa.AssetAssetBundleBuildRule), GUILayout.Width(200.0f)); GUILayout.Label(string.Format("AssetBundleName : {0}", pa.getPackageAssetABName()), GUILayout.Width(400.0f)); GUILayout.EndHorizontal(); }
private PackageAsset() { mAssetObject = null; mPackageAssetType = AssetPackageType.E_INVALIDE; mAssetAssetBundleBuildRule = AssetABBuildRule.E_INVALIDE; mAssetPath = string.Empty; mDependentPackageAsset = null; mInvalideBuildRuleList = null; }
public static PackageResource FindIcon(this PackageAsset asset) { for (int i = 0; i < asset.Resources.Length; i++) { if (asset.Resources[i].Name.EndsWith(".png", System.StringComparison.Ordinal)) { return(asset.Resources[i]); } } return(default(PackageResource)); }
/// <summary> /// 显示依赖资源信息UI /// </summary> /// <param name="assetpath"></param> /// <param name="dpassetpath"></param> private void showAssetDpUI(PackageAsset pa) { GUILayout.BeginHorizontal(); var temppa = pa; GUILayout.Label(string.Format("{0}", Path.GetFileName(temppa.AssetPath)), GUILayout.Width(300.0f)); while (temppa.DependentPackageAsset != null) { GUILayout.Label(" <- ", GUILayout.Width(30.0f)); GUILayout.Label(string.Format("{0}", Path.GetFileName(temppa.DependentPackageAsset.AssetPath)), GUILayout.Width(300.0f)); temppa = temppa.DependentPackageAsset; } GUILayout.EndHorizontal(); }
List <PackageAsset> GetAssets(MemoryStream stream) { var allRecords = new List <PackageAsset>(); var config = new global::ChoETL.ChoCSVRecordConfiguration { FileHeaderConfiguration = new global::ChoETL.ChoCSVFileHeaderConfiguration { HasHeaderRecord = false, }, }; using (var reader = new StreamReader(stream)) foreach (var record in new global::ChoETL.ChoCSVReader <PackageAssetData>(reader, config)) { var asset = new PackageAsset(); asset.Read(i => record.GetString(i)); allRecords.Add(asset); } return(allRecords); }
public void Render(PackageAsset asset) { Name.text = asset.Root; Icon.texture = asset.FindIcon().LoadImage(); }
/// <summary> /// Get all of the dependencies in the specified directory set. /// </summary> private bool GetPackageAssetsCore(TextWriter textWriter, bool isDesktop, List <PackageAsset> packageAssets, params string[] directoryPaths) { var relativeNameMap = new Dictionary <string, PackageAsset>(PathComparer); var allGood = true; IEnumerable <string> enumerateAssets(string directory, SearchOption searchOption = SearchOption.TopDirectoryOnly) { return(Directory .EnumerateFiles(directory, "*.*", searchOption) .Where(IsTrackedAsset)); } // This will record all of the assets files in a directory. The name of the assets and the checksum of the contents will // be added to the map void recordDependencies(MD5 md5, string directory) { // Need to consider the files in the immediate directory and those in the runtimes directory. The resource dlls // are unique and simple to include hence we don't go through the process of verifying them. IEnumerable <string> enumerateFiles() { foreach (var filePath in enumerateAssets(directory)) { yield return(filePath); } var runtimeDirectory = Path.Combine(directory, "runtimes"); if (Directory.Exists(runtimeDirectory)) { foreach (var filePath in enumerateAssets(runtimeDirectory, SearchOption.AllDirectories)) { yield return(filePath); } } } var normalizedDirectoryName = (directory[directory.Length - 1] == '\\') ? directory : directory + @"\"; string getRelativeName(string filePath) => filePath.Substring(normalizedDirectoryName.Length); var foundOne = false; foreach (var assetFilePath in enumerateFiles()) { foundOne = true; using (var stream = File.Open(assetFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { var assetRelativeName = getRelativeName(assetFilePath); var hash = md5.ComputeHash(stream); var hashString = BitConverter.ToString(hash); if (relativeNameMap.TryGetValue(assetRelativeName, out PackageAsset existingAsset)) { // Make sure that all copies of the DLL have the same contents. The DLLs are being merged into // a single directory in the resulting NuGet. If the contents are different then our merge is // invalid. if (existingAsset.Checksum != hashString) { textWriter.WriteLine($"Asset {assetRelativeName} exists at two different versions"); textWriter.WriteLine($"\tHash 1: {hashString}"); textWriter.WriteLine($"\tHash 2: {existingAsset.Checksum}"); allGood = false; } } else { var packageAsset = new PackageAsset(assetRelativeName, hashString, isDesktop); packageAssets.Add(packageAsset); relativeNameMap[assetRelativeName] = packageAsset; } } } if (!foundOne) { textWriter.WriteLine($"Directory {directory} did not have any assets"); allGood = false; } } using (var md5 = MD5.Create()) { foreach (var directory in directoryPaths) { recordDependencies(md5, Path.Combine(ArtifactsDirectory, "bin", directory)); } } return(allGood); }
/// <summary> /// 根据Asset资源类型创建对应的Package Asset对象(创建PackageAsset统一入口) /// </summary> /// <param name="asset">当前Asset</param> /// <param name="dependentasset">依赖当前Asset的Asset</param> /// <returns></returns> public static PackageAsset createPackageAsset(Object asset, Object dependentasset = null) { if (asset != null) { var assetpath = AssetDatabase.GetAssetPath(asset); var assettype = ABHelper.Singleton.getAssetPackageType(assetpath); PackageAsset pa = null; switch (assettype) { case AssetPackageType.E_SCENE: pa = new ScenePackageAsset(asset, dependentasset); break; case AssetPackageType.E_PREFAB: pa = new PrefabPackageAsset(asset, dependentasset); break; case AssetPackageType.E_FBX: pa = new FBXPackageAsset(asset, dependentasset); break; case AssetPackageType.E_ANIMATIONCLIP: pa = new AnimationClipPackageAsset(asset, dependentasset); break; case AssetPackageType.E_ANICONTROLLER: pa = new AnimationControllerPackageAsset(asset, dependentasset); break; case AssetPackageType.E_MATERIAL: pa = new MaterialPackageAsset(asset, dependentasset); break; case AssetPackageType.E_TEXTURE: pa = new TexturePackageAsset(asset, dependentasset); break; case AssetPackageType.E_AUDIOS: pa = new AudiosPackageAsset(asset, dependentasset); break; case AssetPackageType.E_NAVMESH: pa = new ScenePackageAsset(asset, dependentasset); break; case AssetPackageType.E_SHADER: pa = new ShaderPackageAsset(asset, dependentasset); break; case AssetPackageType.E_EDITOR_ASSET: pa = new EditorAssetPackageAsset(asset, dependentasset); break; default: break; } return(pa); } else { return(null); } }
/// <summary> /// 得出所有需要参与打包Asset的PackageAsset抽象 /// </summary> /// <param name="asset">需要参与打包的主Asset</param> /// <param name="packageassetmap">Asset打包映射map,Key為Asset相对路径,Value為Asset打包抽象对象</param> /// <param name="assetqueue">需要参与获取PackageAsset的Asset队列</param> /// <param name="dependentasset">依赖使用参与打包的主Asset的Asset</param> /// <returns>Asset打包是否成功</returns> private static bool getPackageAssets(Object asset, ref Dictionary <string, PackageAsset> packageassetmap, ref Queue <KeyValuePair <Object, Object> > assetqueue, Object dependentasset = null) { if (asset == null) { return(true); } else { var assetpath = AssetDatabase.GetAssetPath(asset); if (!ABHelper.Singleton.isValideAssetFile(assetpath)) { return(true); } else { if (packageassetmap.ContainsKey(assetpath)) { //如果包含了,那么就把对应Asset的Dependent Asset修改为更里层的Dependent Asset //确保每一个Asset对应唯一一个PackageAsset且Dependent Asset信息为最里层的信息 //e.g. Scene -> M1 + M2 Scene -> P1 P1 -> F1 -> M1 //那么对于材质M1而言,最里层DependentAsset引用是F1而非Scene //对于材质M2而言,最里层DepdentAsset引用是Scene var depdendentassetpath = AssetDatabase.GetAssetPath(dependentasset); //if (packageassetmap[assetpath].AssetAssetBundleBuildRule == AssetABBuildRule.E_NORMAL) //{ // var olddppatype = packageassetmap[assetpath].DependentPackageAsset.PackageAssetType; // var newdppatype = packageassetmap[depdendentassetpath].PackageAssetType; // var olddependentpaassetpath = packageassetmap[assetpath].DependentPackageAsset.AssetPath; // var newdppaassetpath = packageassetmap[depdendentassetpath].AssetPath; // //Normal Asset被不同资源但类型相同引用存在潜在问题 // //e.g. // //打包时如果只有Prefab1 -> M1 Prefab2 -> M1会导致M1只跟其中一个打包在一起其中一个Prefab依赖另一个Prefab的AB // //出现M1打包规则为NormalRule时被多个Prefab引用时,需要确保打包机制得出的最终结论M1不属于Prefab层,而属于其他层比如FBX(EntireRule) // //所以如果M1不是作为跟随FBX层打包又被多个Prefab使用的话,建议使用ShareRule打包M1 // if (olddppatype == newdppatype && !olddependentpaassetpath.Equals(newdppaassetpath)) // { // Debug.LogWarning(string.Format("Asset Path: {0}打包規則為NormalRule,但被多個同類型Asset引用:Dp1:{1} Dp2:{2}!", assetpath, olddependentpaassetpath, newdppaassetpath)); // return false; // } //} // 依赖当前Asset的Asset信息不为空,且最新的依赖当前Asset的Asset资源类型与当前依赖的Asset资源类型一致 // 说明有E_NORMAL打包规则的资源被多个同类型资源引用 // 这是不允许的,如果资源被多个资源引用,不允许设定E_NORMAL,因为同一个Asset不能指定多个ABName // 建议设置E_SHARE if (packageassetmap[assetpath].AssetAssetBundleBuildRule == AssetABBuildRule.E_NORMAL && packageassetmap[assetpath].DependentPackageAsset != null && packageassetmap[assetpath].DependentPackageAsset.PackageAssetType == packageassetmap[depdendentassetpath].PackageAssetType) { Debug.Log(string.Format("资源:{0} 打包规则E_NORMAL,被多个同类型资源引用 : 资源1 : {1} 资源2 : {2},建议设置成E_SHARE打包规则!", assetpath, packageassetmap[assetpath].DependentPackageAsset.AssetPath, packageassetmap[depdendentassetpath].AssetPath)); return(false); } else { packageassetmap[assetpath].DependentPackageAsset = packageassetmap[depdendentassetpath]; } } else { var packageasset = PackageAsset.createPackageAsset(asset, dependentasset); if (packageasset != null) { packageassetmap.Add(assetpath, packageasset); // 将依赖使用当前Asset的PackageAsset信息指向同一个PackageAsset var dpassetpath = AssetDatabase.GetAssetPath(dependentasset); if (packageassetmap.ContainsKey(dpassetpath)) { packageassetmap[assetpath].DependentPackageAsset = packageassetmap[dpassetpath]; } } else { Debug.LogError(string.Format("Asset Path創建PackageAsset失敗!Asset Path: {0}", assetpath)); return(false); } } //这里的false参数是为了一层一层取出Asset的依赖关系,然后整理出Asset的层级关系,确保每一个Asset只对应一个最终的PackageAsset var dps = AssetDatabase.GetDependencies(assetpath, false); foreach (var dp in dps) { if (!ABHelper.Singleton.isValideAssetFile(dp)) { continue; } var dpasset = AssetDatabase.LoadAssetAtPath <Object>(dp); assetqueue.Enqueue(new KeyValuePair <Object, Object>(dpasset, asset)); } return(true); } } }