public override void OnImportAsset(AssetImportContext ctx)
        {
            try
            {
                ctx.DependsOnCustomDependency("EntityBinaryFileFormatVersion");

                var sceneWithBuildConfiguration = SceneWithBuildConfigurationGUIDs.ReadFromFile(ctx.assetPath);

                // Ensure we have as many dependencies as possible registered early in case an exception is thrown
                var scenePath = AssetDatabase.GUIDToAssetPath(sceneWithBuildConfiguration.SceneGUID.ToString());
                ctx.DependsOnSourceAsset(scenePath);

                if (sceneWithBuildConfiguration.BuildConfiguration.IsValid)
                {
                    var buildConfigurationPath = AssetDatabase.GUIDToAssetPath(sceneWithBuildConfiguration.BuildConfiguration.ToString());
                    ctx.DependsOnSourceAsset(buildConfigurationPath);
                    var buildConfigurationDependencies = AssetDatabase.GetDependencies(buildConfigurationPath);
                    foreach (var dependency in buildConfigurationDependencies)
                    {
                        ctx.DependsOnSourceAsset(dependency);
                    }
                }

                var dependencies = AssetDatabase.GetDependencies(scenePath);
                foreach (var dependency in dependencies)
                {
                    if (dependency.ToLower().EndsWith(".prefab"))
                    {
                        ctx.DependsOnSourceAsset(dependency);
                    }
                }

                var config = BuildConfiguration.LoadAsset(sceneWithBuildConfiguration.BuildConfiguration);

                var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);

                try
                {
                    var settings = new GameObjectConversionSettings();

                    settings.SceneGUID          = sceneWithBuildConfiguration.SceneGUID;
                    settings.BuildConfiguration = config;
                    settings.AssetImportContext = ctx;

                    var sectionRefObjs = new List <ReferencedUnityObjects>();
                    var sectionData    = EditorEntityScenes.ConvertAndWriteEntityScene(scene, settings, sectionRefObjs);
                    WriteRefGuids(sectionRefObjs, sectionData, ctx);
                }
                finally
                {
                    EditorSceneManager.CloseScene(scene, true);
                }
            }
            // Currently it's not acceptable to let the asset database catch the exception since it will create a default asset without any dependencies
            // This means a reimport will not be triggered if the scene is subsequently modified
            catch (Exception e)
            {
                Debug.Log($"Exception thrown during SubScene import: {e}");
            }
        }
Exemple #2
0
 public static void TearDownOnce()
 {
     s_Assets.TearDown();
     LiveLinkEditorEventSystem.InitializeLiveLinkSystems();
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
     EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
 }
Exemple #3
0
        public static void Check(string path)
        {
            var guid = AssetDatabaseCompatibility.PathToGUID(path);

            Assert.IsFalse(guid.Empty());

            var configGUID = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(guid, default, true, out var requireRefresh);
        public void OneTimeTearDown()
        {
            UnityEngine.Object.DestroyImmediate(m_SubSceneRoot);
            AssetDatabase.DeleteAsset(m_TestAssetsDirectory);
            SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
            EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);

            SubSceneInspectorUtility.LiveLinkEnabledInEditMode = m_PreviousLiveLinkState;
        }
Exemple #5
0
 public void OneTimeTearDown()
 {
     // Clean up all test assets
     EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
     AssetDatabase.DeleteAsset(m_TempAssetDir);
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
     SubSceneInspectorUtility.LiveLinkEnabledInEditMode = m_WasLiveLinkEnabled;
     EditorSettings.enterPlayModeOptions        = m_EnterPlayModeOptions;
     EditorSettings.enterPlayModeOptionsEnabled = m_UseEnterPlayerModeOptions;
 }
 public void OneTimeTearDown()
 {
     // Clean up all test assets
     m_Assets.TearDown();
     m_DefaultWorld.TearDown();
     EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
     SubSceneInspectorUtility.LiveLinkEnabledInEditMode = m_WasLiveLinkEnabled;
     EditorSettings.enterPlayModeOptions        = m_EnterPlayModeOptions;
     EditorSettings.enterPlayModeOptionsEnabled = m_UseEnterPlayerModeOptions;
 }
Exemple #7
0
        public static void TearDown()
        {
            var connections = s_Connection.OpenConnections.ToArray();
            foreach (var connectedPlayer in connections)
                s_Connection.PostDisconnect(connectedPlayer);

            s_Assets.TearDown();
            LiveLinkEditorEventSystem.InitializeLiveLinkSystems();
            SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
            EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
        }
Exemple #8
0
        // 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 = AssetDatabaseCompatibility.GetArtifactHash(hash128Guid.ToString(), typeof(SubSceneImporter), ImportMode.Synchronous);
                AssetDatabaseCompatibility.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);
Exemple #9
0
 public static void ForceReimport(params SubScene[] scenes)
 {
     bool needRefresh = false;
     foreach (var world in World.All)
     {
         var sceneSystem = world.GetExistingSystem<SceneSystem>();
         if (sceneSystem != null)
         {
             foreach (var scene in scenes)
                 needRefresh |= SceneWithBuildConfigurationGUIDs.Dirty(scene.SceneGUID, sceneSystem.BuildConfigurationGUID);
         }
     }
     if (needRefresh)
         AssetDatabase.Refresh();
 }
Exemple #10
0
        public void SetUpOnce()
        {
#if UNITY_EDITOR
            try
            {
                BuildConfiguration.CreateAsset(m_BuildConfigPath, config =>
                {
                    config.SetComponent(new SceneList
                    {
                        SceneInfos = new List <SceneList.SceneInfo>
                        {
                            new SceneList.SceneInfo
                            {
                                Scene = GlobalObjectId.GetGlobalObjectIdSlow(
                                    AssetDatabase.LoadAssetAtPath <SceneAsset>(m_SubScenePath))
                            }
                        }
                    });
                });
                m_BuildConfigurationGUID = new GUID(AssetDatabase.AssetPathToGUID(m_BuildConfigPath));
                m_SceneGUID = new GUID(AssetDatabase.AssetPathToGUID(m_SubScenePath));

                var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(m_SceneGUID, m_BuildConfigurationGUID, true,
                                                                            out var requestRefresh);
                if (requestRefresh)
                {
                    AssetDatabase.Refresh();
                }
                m_SceneWithBuildSettingsPath = SceneWithBuildConfigurationGUIDs.GetSceneWithBuildSettingsPath(guid);
                EntityScenesPaths.GetSubSceneArtifactHash(m_SceneGUID, m_BuildConfigurationGUID, true,
                                                          ImportMode.Synchronous);
            }
            catch
            {
                AssetDatabase.DeleteAsset(m_TempPath);
                AssetDatabase.DeleteAsset(m_SceneWithBuildSettingsPath);
                throw;
            }

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
#else
            //TODO: Playmode test not supported yet
            m_SceneGUID = new Unity.Entities.Hash128();
#endif
        }
        static void AddEntityBinaryFiles(Hash128 buildConfigurationGuid, string[] scenePathsForBuild, EntitySectionBundlesInBuild sectionBundlesInBuild)
        {
            var subSceneGuids = scenePathsForBuild.SelectMany(scenePath => EditorEntityScenes.GetSubScenes(AssetDatabaseCompatibility.PathToGUID(scenePath))).Distinct().ToList();

            var requiresRefresh       = false;
            var sceneBuildConfigGuids = new NativeArray <GUID>(subSceneGuids.Count, Allocator.TempJob);

            for (int i = 0; i != sceneBuildConfigGuids.Length; i++)
            {
                sceneBuildConfigGuids[i] = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(subSceneGuids[i], buildConfigurationGuid, false, out var thisRequiresRefresh);
                requiresRefresh         |= thisRequiresRefresh;

                sectionBundlesInBuild.Add(subSceneGuids[i], sceneBuildConfigGuids[i], typeof(SubSceneImporter));
            }
            if (requiresRefresh)
            {
                AssetDatabase.Refresh();
            }

            AssetDatabaseCompatibility.ProduceArtifactsAsync(sceneBuildConfigGuids, typeof(SubSceneImporter));
            sceneBuildConfigGuids.Dispose();
        }
Exemple #12
0
 public void TearDownOnce()
 {
     m_TempAssets.TearDown();
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
 }
Exemple #13
0
        public override BuildResult Run(BuildContext context)
        {
            var manifest               = context.BuildManifest;
            var rootAssembly           = context.GetComponentOrDefault <DotsRuntimeRootAssembly>();
            var buildScenes            = context.GetComponentOrDefault <SceneList>();
            var targetName             = rootAssembly.MakeBeeTargetName(context.BuildConfigurationName);
            var scenePaths             = buildScenes.GetScenePathsForBuild();
            var buildConfigurationGuid = context.BuildConfigurationAssetGUID;
            var dataDirectory          = WorldExport.GetOrCreateDataDirectoryFrom(rootAssembly.StagingDirectory.Combine(targetName));
            var logsDirectory          = WorldExport.GetOrCreateLogDirectoryFrom(targetName);

            var sceneGuids = scenePaths.SelectMany(scenePath =>
            {
                var guids = EditorEntityScenes.GetSubScenes(AssetDatabaseCompatibility.PathToGUID(scenePath)).ToList();
                guids.Add(AssetDatabaseCompatibility.PathToGUID(scenePath));
                return(guids);
            }).Distinct().ToList();

            //Save all unsaved scenes of the project first
            foreach (var guid in sceneGuids)
            {
                string scenePath = AssetDatabase.GUIDToAssetPath(guid.ToString());
                var    scene     = SceneManager.GetSceneByPath(scenePath);
                EditorSceneManager.SaveScene(scene);
            }

            var requiresRefresh       = false;
            var sceneBuildConfigGuids = new NativeArray <GUID>(sceneGuids.Count, Allocator.TempJob);

            for (int i = 0; i != sceneBuildConfigGuids.Length; i++)
            {
                sceneBuildConfigGuids[i] = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(sceneGuids[i], new Hash128(buildConfigurationGuid), false, out var thisRequiresRefresh);
                requiresRefresh         |= thisRequiresRefresh;
            }
            if (requiresRefresh)
            {
                AssetDatabase.Refresh();
            }

            var artifactHashes = new NativeArray <UnityEngine.Hash128>(sceneGuids.Count, Allocator.TempJob);

            AssetDatabaseCompatibility.ProduceArtifactsRefreshIfNecessary(sceneBuildConfigGuids, typeof(SubSceneImporter), artifactHashes);

            bool succeeded = true;

            for (int i = 0; i != sceneBuildConfigGuids.Length; i++)
            {
                var sceneGuid    = sceneGuids[i];
                var artifactHash = artifactHashes[i];

                AssetDatabaseCompatibility.GetArtifactPaths(artifactHash, out var artifactPaths);

                List <FileInfo> exportedFiles     = new List <FileInfo>();
                bool            foundEntityHeader = false;
                foreach (var artifactPath in artifactPaths)
                {
                    var ext = Path.GetExtension(artifactPath).ToLower().Replace(".", "");
                    if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesHeader))
                    {
                        foundEntityHeader = true;
                        var destinationFile = dataDirectory.FullName + Path.DirectorySeparatorChar + EntityScenesPaths.RelativePathFolderFor(sceneGuid, EntityScenesPaths.PathType.EntitiesHeader, -1);
                        new NPath(artifactPath).MakeAbsolute().Copy(new NPath(destinationFile).MakeAbsolute().EnsureParentDirectoryExists());
                        exportedFiles.Add(new FileInfo(destinationFile));
                    }
                    else if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesBinary))
                    {
                        var destinationFile = dataDirectory.FullName + Path.DirectorySeparatorChar + EntityScenesPaths.RelativePathFolderFor(sceneGuid, EntityScenesPaths.PathType.EntitiesBinary, EntityScenesPaths.GetSectionIndexFromPath(artifactPath));
                        new NPath(artifactPath).MakeAbsolute().Copy(new NPath(destinationFile).MakeAbsolute().EnsureParentDirectoryExists());
                        exportedFiles.Add(new FileInfo(destinationFile));
                    }
                    else if (ext == EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesConversionLog))
                    {
                        var destinationFile = logsDirectory.FullName + Path.DirectorySeparatorChar + $"{sceneGuid}.{EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesConversionLog)}";
                        new NPath(artifactPath).MakeAbsolute().Copy(new NPath(destinationFile).MakeAbsolute().EnsureParentDirectoryExists());
                        var result = PrintConversionLogToUnityConsole(artifactPath);
                        if (result.HasError || result.HasException)
                        {
                            UnityEngine.Debug.LogError("Failed to export scene: " + Path.GetFileName(AssetDatabase.GUIDToAssetPath(sceneGuid.ToString())));
                            succeeded = false;
                        }
                    }
                    else if (new Hash128(ext).IsValid) //Asset files are exported as {artifactHash}.{assetguid}
                    {
                        var destinationFile = dataDirectory.FullName + Path.DirectorySeparatorChar + ext;
                        new NPath(artifactPath).MakeAbsolute().Copy(new NPath(destinationFile).MakeAbsolute().EnsureParentDirectoryExists());
                        exportedFiles.Add(new FileInfo(destinationFile));
                    }
                }

                if (!foundEntityHeader)
                {
                    Debug.LogError($"Failed to build EntityScene for '{AssetDatabaseCompatibility.GuidToPath(sceneGuid)}'.");
                    succeeded = false;
                }

                //UpdateManifest
                manifest.Add(new Guid(sceneGuid.ToString()), AssetDatabase.GUIDToAssetPath(sceneGuid.ToString()), exportedFiles);
            }

            var catalogPath = Path.Combine(dataDirectory.ToString(), SceneSystem.k_SceneInfoFileName);

            WriteCatalogFile(catalogPath, buildScenes);
            manifest.AddAdditionalFilesToDeploy(new FileInfo(catalogPath.ToString()));

            sceneBuildConfigGuids.Dispose();
            artifactHashes.Dispose();

            if (succeeded)
            {
                return(context.Success());
            }
            return(context.Failure($"Failed to export scenes"));
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            try
            {
                var sceneWithBuildConfiguration = SceneWithBuildConfigurationGUIDs.ReadFromFile(ctx.assetPath);

                // Ensure we have as many dependencies as possible registered early in case an exception is thrown
                EditorEntityScenes.AddEntityBinaryFileDependencies(ctx, sceneWithBuildConfiguration.BuildConfiguration);
                EditorEntityScenes.DependOnSceneGameObjects(sceneWithBuildConfiguration.SceneGUID, ctx);

                var config = BuildConfiguration.LoadAsset(sceneWithBuildConfiguration.BuildConfiguration);

                var scenePath = AssetDatabaseCompatibility.GuidToPath(sceneWithBuildConfiguration.SceneGUID);
                var scene     = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);
                try
                {
                    EditorSceneManager.SetActiveScene(scene);

                    var settings = new GameObjectConversionSettings();

                    settings.SceneGUID = sceneWithBuildConfiguration.SceneGUID;
                    if (!sceneWithBuildConfiguration.IsBuildingForEditor)
                    {
                        settings.ConversionFlags |= GameObjectConversionUtility.ConversionFlags.IsBuildingForPlayer;
                    }

                    settings.BuildConfiguration = config;
                    settings.AssetImportContext = ctx;
                    settings.FilterFlags        = WorldSystemFilterFlags.HybridGameObjectConversion;

                    WriteEntitySceneSettings writeEntitySettings = new WriteEntitySceneSettings();
                    if (config != null && config.TryGetComponent <DotsRuntimeBuildProfile>(out var profile))
                    {
                        if (config.TryGetComponent <DotsRuntimeRootAssembly>(out var rootAssembly))
                        {
                            writeEntitySettings.Codec              = Codec.LZ4;
                            writeEntitySettings.IsDotsRuntime      = true;
                            writeEntitySettings.BuildAssemblyCache = new BuildAssemblyCache()
                            {
                                BaseAssemblies = rootAssembly.RootAssembly.asset,
                                PlatformName   = profile.Target.UnityPlatformName
                            };
                            settings.FilterFlags = WorldSystemFilterFlags.DotsRuntimeGameObjectConversion;

                            //Updating the root asmdef references or its references should re-trigger conversion
                            ctx.DependsOnArtifact(AssetDatabase.GetAssetPath(rootAssembly.RootAssembly.asset));
                            foreach (var assemblyPath in writeEntitySettings.BuildAssemblyCache.AssembliesPath)
                            {
                                ctx.DependsOnArtifact(assemblyPath);
                            }
                        }
                    }

                    var sectionRefObjs = new List <ReferencedUnityObjects>();
                    var sectionData    = EditorEntityScenes.ConvertAndWriteEntityScene(scene, settings, sectionRefObjs, writeEntitySettings);

                    WriteAssetDependencyGUIDs(sectionRefObjs, sectionData, ctx);

                    foreach (var objRefs in sectionRefObjs)
                    {
                        DestroyImmediate(objRefs);
                    }
                }
                finally
                {
                    EditorSceneManager.CloseScene(scene, true);
                }
            }
            // Currently it's not acceptable to let the asset database catch the exception since it will create a default asset without any dependencies
            // This means a reimport will not be triggered if the scene is subsequently modified
            catch (Exception e)
            {
                Debug.Log($"Exception thrown during SubScene import: {e}");
            }
        }
Exemple #15
0
        // 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, string[] scenePathsForBuild, BuildTarget target, Action <string, string> RegisterFileCopy, string outputStreamingAssetsDirectory, string buildWorkingDirectory)
        {
            if (target == BuildTarget.NoTarget)
            {
                throw new InvalidOperationException($"Invalid build target '{target.ToString()}'.");
            }

            if (target != EditorUserBuildSettings.activeBuildTarget)
            {
                throw new InvalidOperationException($"ActiveBuildTarget must be switched before the {nameof(SubSceneBuildCode)} runs.");
            }

            var content             = new BundleBuildContent(new AssetBundleBuild[0]);
            var bundleNames         = new HashSet <string>();
            var subSceneGuids       = scenePathsForBuild.SelectMany(scenePath => SceneMetaDataImporter.GetSubSceneGuids(AssetDatabase.AssetPathToGUID(scenePath))).Distinct().ToList();
            var subScenePaths       = new Dictionary <Hash128, string>();
            var dependencyInputData = new Dictionary <SceneSection, SectionDependencyInfo>();
            var refExt    = EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesUnityObjectReferences);
            var headerExt = EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesHeader);
            var binaryExt = EntityScenesPaths.GetExtension(EntityScenesPaths.PathType.EntitiesBinary);

            var group      = BuildPipeline.GetBuildTargetGroup(target);
            var parameters = new BundleBuildParameters(target, @group, buildWorkingDirectory)
            {
                BundleCompression = BuildCompression.LZ4Runtime
            };

            var requiresRefresh       = false;
            var sceneBuildConfigGuids = new NativeArray <GUID>(subSceneGuids.Count, Allocator.TempJob);

            for (int i = 0; i != sceneBuildConfigGuids.Length; i++)
            {
                sceneBuildConfigGuids[i] = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(subSceneGuids[i], new Hash128(buildConfigurationGuid), out var thisRequiresRefresh);
                requiresRefresh         |= thisRequiresRefresh;
            }
            if (requiresRefresh)
            {
                AssetDatabase.Refresh();
            }

            var artifactHashes = new NativeArray <UnityEngine.Hash128>(subSceneGuids.Count, Allocator.TempJob);

            AssetDatabaseCompatibility.ProduceArtifactsRefreshIfNecessary(sceneBuildConfigGuids, typeof(SubSceneImporter), artifactHashes);

            for (int i = 0; i != sceneBuildConfigGuids.Length; i++)
            {
                var sceneGuid            = subSceneGuids[i];
                var sceneBuildConfigGuid = sceneBuildConfigGuids[i];
                var artifactHash         = artifactHashes[i];

                bool foundEntityHeader = false;
                AssetDatabaseCompatibility.GetArtifactPaths(artifactHash, out var artifactPaths);
                foreach (var artifactPath in artifactPaths)
                {
                    //@TODO: This looks like a workaround. Whats going on here?
                    var ext = Path.GetExtension(artifactPath).Replace(".", "");
                    if (ext == headerExt)
                    {
                        foundEntityHeader = true;

                        if (!string.IsNullOrEmpty(artifactPaths.FirstOrDefault(a => a.EndsWith(refExt))))
                        {
                            subScenePaths[sceneGuid] = artifactPath;
                        }
                        else
                        {
                            //if there are no reference bundles, then deduplication can be skipped
                            var destinationFile = EntityScenesPaths.RelativePathFolderFor(sceneGuid, EntityScenesPaths.PathType.EntitiesHeader, -1);
                            DoCopy(RegisterFileCopy, outputStreamingAssetsDirectory, artifactPath, destinationFile);
                        }
                    }
                    else if (ext == binaryExt)
                    {
                        var destinationFile = EntityScenesPaths.RelativePathFolderFor(sceneGuid, EntityScenesPaths.PathType.EntitiesBinary, EntityScenesPaths.GetSectionIndexFromPath(artifactPath));
                        DoCopy(RegisterFileCopy, outputStreamingAssetsDirectory, artifactPath, destinationFile);
                    }

                    if (ext == refExt)
                    {
                        content.CustomAssets.Add(new CustomContent
                        {
                            Asset     = sceneBuildConfigGuid,
                            Processor = (guid, processor) =>
                            {
                                var sectionIndex = EntityScenesPaths.GetSectionIndexFromPath(artifactPath);
                                processor.GetObjectIdentifiersAndTypesForSerializedFile(artifactPath, out ObjectIdentifier[] objectIds, out Type[] types);
Exemple #16
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            try
            {
                ctx.DependsOnCustomDependency("EntityBinaryFileFormatVersion");
                ctx.DependsOnCustomDependency("SceneMetaDataFileFormatVersion");
                ctx.DependsOnSourceAsset(EntitiesCacheUtility.globalEntitySceneDependencyPath);

                var sceneWithBuildConfiguration = SceneWithBuildConfigurationGUIDs.ReadFromFile(ctx.assetPath);

                // Ensure we have as many dependencies as possible registered early in case an exception is thrown
                var scenePath = AssetDatabase.GUIDToAssetPath(sceneWithBuildConfiguration.SceneGUID.ToString());
                ctx.DependsOnSourceAsset(scenePath);

                if (sceneWithBuildConfiguration.BuildConfiguration.IsValid)
                {
                    var buildConfigurationPath = AssetDatabase.GUIDToAssetPath(sceneWithBuildConfiguration.BuildConfiguration.ToString());
                    ctx.DependsOnSourceAsset(buildConfigurationPath);
                    var buildConfigurationDependencies = AssetDatabase.GetDependencies(buildConfigurationPath);
                    foreach (var dependency in buildConfigurationDependencies)
                    {
                        ctx.DependsOnSourceAsset(dependency);
                    }
                }

                var dependencies = AssetDatabase.GetDependencies(scenePath);
                foreach (var dependency in dependencies)
                {
                    if (dependency.ToLower().EndsWith(".prefab"))
                    {
                        ctx.DependsOnSourceAsset(dependency);
                    }
                }

                var config = BuildConfiguration.LoadAsset(sceneWithBuildConfiguration.BuildConfiguration);

                var scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive);

                try
                {
                    var settings = new GameObjectConversionSettings();

                    settings.SceneGUID          = sceneWithBuildConfiguration.SceneGUID;
                    settings.BuildConfiguration = config;
                    settings.AssetImportContext = ctx;
                    settings.FilterFlags        = WorldSystemFilterFlags.HybridGameObjectConversion;

                    WriteEntitySceneSettings writeEntitySettings = new WriteEntitySceneSettings();
                    if (config != null && config.TryGetComponent <DotsRuntimeBuildProfile>(out var profile))
                    {
                        if (config.TryGetComponent <DotsRuntimeRootAssembly>(out var rootAssembly))
                        {
                            ctx.DependsOnSourceAsset(AssetDatabase.GetAssetPath(rootAssembly.RootAssembly.asset));
                            EditorSceneManager.SetActiveScene(scene);
                            writeEntitySettings.Codec              = Codec.LZ4;
                            writeEntitySettings.IsDotsRuntime      = true;
                            writeEntitySettings.BuildAssemblyCache = new BuildAssemblyCache()
                            {
                                BaseAssemblies = rootAssembly.RootAssembly.asset,
                                PlatformName   = profile.Target.UnityPlatformName
                            };
                            settings.FilterFlags = WorldSystemFilterFlags.DotsRuntimeGameObjectConversion;
                        }
                    }

                    var sectionRefObjs = new List <ReferencedUnityObjects>();
                    var sectionData    = EditorEntityScenes.ConvertAndWriteEntitySceneInternal(scene, settings, sectionRefObjs, writeEntitySettings);

                    WriteAssetDependencyGUIDs(sectionRefObjs, sectionData, ctx);
                }
                finally
                {
                    EditorSceneManager.CloseScene(scene, true);
                }
            }
            // Currently it's not acceptable to let the asset database catch the exception since it will create a default asset without any dependencies
            // This means a reimport will not be triggered if the scene is subsequently modified
            catch (Exception e)
            {
                Debug.Log($"Exception thrown during SubScene import: {e}");
            }
        }
 public void TearDown()
 {
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
     EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
 }
Exemple #18
0
 public void OneTimeTearDown()
 {
     AssetDatabase.DeleteAsset(m_TempAssetDir);
     SceneWithBuildConfigurationGUIDs.ClearBuildSettingsCache();
 }