public static string GetLibraryFullPath(string guid) { if (String.IsNullOrEmpty(guid)) { return(null); } string path = AssetDatabase.GUIDToAssetPath(guid); if (Path.GetExtension(path).Equals(".asset")) { return(path); } #if UNITY_2019_2_OR_NEWER if (EditorSettings.assetPipelineMode == AssetPipelineMode.Version1) { return(GetAssetDatabaseVersion1LibraryDataPath(guid)); } else { #if UNITY_2020_2_OR_NEWER Hash128 artifactHash = AssetDatabaseExperimental.LookupArtifact(new ArtifactKey(new GUID(guid))).value; #else Hash128 artifactHash = AssetDatabaseExperimental.GetArtifactHash(guid); #endif if (!artifactHash.isValid) { return(null); } #if UNITY_2020_2_OR_NEWER ArtifactID artifactID = new ArtifactID(); artifactID.value = artifactHash; AssetDatabaseExperimental.GetArtifactPaths(artifactID, out string[] paths); #else AssetDatabaseExperimental.GetArtifactPaths(artifactHash, out string[] paths); #endif foreach (string artifactPath in paths) { if (artifactPath.EndsWith(".info")) { continue; } return(Path.GetFullPath(artifactPath)); } } #else // For older unity versions that dont have asset database V2 yet return(return GetAssetDatabaseVersion1LibraryDataPath(guid)); #endif return(null); }
// This function is responsible for providing all the subscenes to the build. // // The way these files get generated is that we have a SceneWithBuildConfiguration file, (which is a bit of a hack to work around the inability for scriptable importers to take arguments, so // instead we create a different file that points to the scene we want to import, and points to the buildconfiguration we want to import it for). The SubsceneImporter will import this file, // and it will make 3 (relevant) kind of files: // - headerfile // - entitybinaryformat file (the actual entities payloads) // - a SerializedFile that has an array of UnityEngine.Object PPtrs that are used by this entity file. // // The first two we deal with very simply: they just need to be copied into the build, and we're done. // the third one, we will feed as input to the Scriptable build pipeline (which is actually about creating assetbundles), and create an assetbundle that // has all those objects in it that the 3rd file referred to. We do this with a batch api, first we loop through all subscenes, and register with this batch // api which assetbundles we'd like to see produced, and then at the end, we say "okay make them please". this assetbundle creation api has a caching system // that is separate from the assetpipeline caching system, so if all goes well, the call to produce these assetbundles will return very fast and did nothing. // // The reason for the strange looking api, where a two callbacks get passed in is to make integration of the new incremental buildpipeline easier, as this code // needs to be compatible both with the current buildpipeline in the dots-repo, as well as with the incremental buildpipeline. When that is merged, we can simplify this. public static void PrepareAdditionalFiles(string buildConfigurationGuid, Func <Type, IBuildComponent> getRequiredComponent, Action <string, string> RegisterFileCopy, string outputStreamingAssetsDirectory, string buildWorkingDirectory) { T GetRequiredComponent <T>() => (T)getRequiredComponent(typeof(T)); var profile = GetRequiredComponent <ClassicBuildProfile>(); if (profile.Target == BuildTarget.NoTarget) { throw new InvalidOperationException($"Invalid build target '{profile.Target.ToString()}'."); } if (profile.Target != EditorUserBuildSettings.activeBuildTarget) { throw new InvalidOperationException($"ActiveBuildTarget must be switched before the {nameof(SubSceneBuildCode)} runs."); } var content = new BundleBuildContent(new AssetBundleBuild[0]); var sceneList = GetRequiredComponent <SceneList>(); var bundleNames = new List <string>(); var subSceneGuids = sceneList.GetScenePathsForBuild().SelectMany(scenePath => SceneMetaDataImporter.GetSubSceneGuids(AssetDatabase.AssetPathToGUID(scenePath))).Distinct().ToList(); foreach (var subSceneGuid in subSceneGuids) { var hash128Guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(subSceneGuid, new Hash128(buildConfigurationGuid)); var hash = AssetDatabaseExperimental.GetArtifactHash(hash128Guid.ToString(), typeof(SubSceneImporter)); AssetDatabaseExperimental.GetArtifactPaths(hash, out var artifactPaths); foreach (var artifactPath in artifactPaths) { var ext = Path.GetExtension(artifactPath).Replace(".", ""); if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesHeader)) { var destinationFile = outputStreamingAssetsDirectory + "/" + EntityScenesPaths.RelativePathInStreamingAssetsFolderFor(subSceneGuid, EntityScenesPaths.PathType.EntitiesHeader, -1); RegisterFileCopy(artifactPath, destinationFile); } if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesBinary)) { var destinationFile = outputStreamingAssetsDirectory + "/" + EntityScenesPaths.RelativePathInStreamingAssetsFolderFor(subSceneGuid, EntityScenesPaths.PathType.EntitiesBinary, EntityScenesPaths.GetSectionIndexFromPath(artifactPath)); RegisterFileCopy(artifactPath, destinationFile); } if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesUnityObjectReferences)) { content.CustomAssets.Add(new CustomContent { Asset = hash128Guid, Processor = (guid, processor) => { var sectionIndex = EntityScenesPaths.GetSectionIndexFromPath(artifactPath); processor.GetObjectIdentifiersAndTypesForSerializedFile(artifactPath, out ObjectIdentifier[] objectIds, out Type[] types);
public static string GetBundlePath(string guid, BuildTarget target) { try { AssetDatabaseExperimental.GetArtifactPaths(GetHash(guid, target), out string[] paths); return(paths.First(o => o.EndsWith(k_BundleExtension))); } catch (Exception e) { UnityEngine.Debug.LogError($"Exception thrown getting bundle path for '{guid}'.\n{e.Message}"); } return(""); }
public unsafe static Hash128[] GetSubSceneGuids(string guid) { var hash = AssetDatabaseExperimental.GetArtifactHash(guid, typeof(SceneMetaDataImporter), AssetDatabaseExperimental.ImportSyncMode.Block); AssetDatabaseExperimental.GetArtifactPaths(hash, out string[] paths); var metaPath = paths.First(o => o.EndsWith("scenemeta")); BlobAssetReference <SceneMetaData> sceneMetaDataRef; if (!BlobAssetReference <SceneMetaData> .TryRead(metaPath, SceneMetaDataImporter.CurrentFileFormatVersion, out sceneMetaDataRef)) { return(new Hash128[0]); } Hash128[] guids = sceneMetaDataRef.Value.SubScenes.ToArray(); sceneMetaDataRef.Dispose(); return(guids); }
// Recursive until new SBP APIs land in 2020.1 public unsafe static Hash128[] GetDependencies(string guid, BuildTarget target) { try { AssetDatabaseExperimental.GetArtifactPaths(GetHash(guid, target), out string[] paths); var metaPath = paths.First(o => o.EndsWith(k_DependenciesExtension)); BlobAssetReference <BuildMetaData> buildMetaData; if (!BlobAssetReference <BuildMetaData> .TryRead(metaPath, k_CurrentFileFormatVersion, out buildMetaData)) { return(new Hash128[0]); } Hash128[] guids = buildMetaData.Value.Dependencies.ToArray(); buildMetaData.Dispose(); return(guids); } catch (Exception e) { UnityEngine.Debug.LogError($"Exception thrown getting dependencies for '{guid}'.\n{e.Message}"); } return(new Hash128[0]); }